Browse Source

Pull request #3800: KERNEL-6368【代码检测】XML注入(XML External Entity Injection)

Merge in DESIGN/design from ~VITO/c-design:KERNEL-6368 to bugfix/10.0

* commit 'be0850e46a6bd224fade40fed6f5ba853f9e8093':
  KERNEL-6368【代码检测】XML注入(XML External Entity Injection)
bugfix/10.0
ju|剧浩宇 4 years ago
parent
commit
186c45dade
  1. 676
      designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java
  2. 4
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java
  3. 9
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java
  4. 8
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java
  5. 5
      designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java

676
designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java

@ -2,7 +2,7 @@
* 12/21/2008 * 12/21/2008
* *
* DefaultCompletionProvider.java - A basic completion provider implementation. * DefaultCompletionProvider.java - A basic completion provider implementation.
* *
* This library is distributed under a modified BSD license. See the included * This library is distributed under a modified BSD license. See the included
* RSyntaxTextArea.License.txt file for details. * RSyntaxTextArea.License.txt file for details.
*/ */
@ -24,7 +24,11 @@ import javax.swing.text.Segment;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParserFactory;
import com.fr.log.FineLoggerFactory;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
/** /**
@ -38,337 +42,345 @@ import org.xml.sax.SAXException;
*/ */
public class DefaultCompletionProvider extends AbstractCompletionProvider { public class DefaultCompletionProvider extends AbstractCompletionProvider {
protected Segment seg; protected Segment seg;
/** /**
* Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}. * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}.
*/ */
private String lastCompletionsAtText; private String lastCompletionsAtText;
/** /**
* Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}, * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)},
* since this may be called multiple times in succession (this is usually * since this may be called multiple times in succession (this is usually
* called by <tt>JTextComponent.getToolTipText()</tt>, and if the user * called by <tt>JTextComponent.getToolTipText()</tt>, and if the user
* wiggles the mouse while a tool tip is displayed, this method gets * wiggles the mouse while a tool tip is displayed, this method gets
* repeatedly called. It can be costly so we try to speed it up a tad). * repeatedly called. It can be costly so we try to speed it up a tad).
*/ */
private List<Completion> lastParameterizedCompletionsAt; private List<Completion> lastParameterizedCompletionsAt;
/** /**
* Constructor. The returned provider will not be aware of any completions. * Constructor. The returned provider will not be aware of any completions.
* *
* @see #addCompletion(Completion) * @see #addCompletion(Completion)
*/ */
public DefaultCompletionProvider() { public DefaultCompletionProvider() {
init(); init();
} }
/** /**
* Creates a completion provider that provides completion for a simple * Creates a completion provider that provides completion for a simple
* list of words. * list of words.
* *
* @param words The words to offer as completion suggestions. If this is * @param words The words to offer as completion suggestions. If this is
* <code>null</code>, no completions will be known. * <code>null</code>, no completions will be known.
* @see BasicCompletion * @see BasicCompletion
*/ */
public DefaultCompletionProvider(String[] words) { public DefaultCompletionProvider(String[] words) {
init(); init();
addWordCompletions(words); addWordCompletions(words);
} }
/** /**
* Returns the text just before the current caret position that could be * Returns the text just before the current caret position that could be
* the start of something auto-completable.<p> * the start of something auto-completable.<p>
* * <p>
* This method returns all characters before the caret that are matched * This method returns all characters before the caret that are matched
* by {@link #isValidChar(char)}. * by {@link #isValidChar(char)}.
* * <p>
* {@inheritDoc} * {@inheritDoc}
*/ */
public String getAlreadyEnteredText(JTextComponent comp) { public String getAlreadyEnteredText(JTextComponent comp) {
Document doc = comp.getDocument(); Document doc = comp.getDocument();
int dot = comp.getCaretPosition(); int dot = comp.getCaretPosition();
Element root = doc.getDefaultRootElement(); Element root = doc.getDefaultRootElement();
int index = root.getElementIndex(dot); int index = root.getElementIndex(dot);
Element elem = root.getElement(index); Element elem = root.getElement(index);
int start = elem.getStartOffset(); int start = elem.getStartOffset();
int len = dot-start; int len = dot - start;
try { try {
doc.getText(start, len, seg); doc.getText(start, len, seg);
} catch (BadLocationException ble) { } catch (BadLocationException ble) {
return EMPTY_STRING; return EMPTY_STRING;
} }
int segEnd = seg.offset + len; int segEnd = seg.offset + len;
start = segEnd - 1; start = segEnd - 1;
while (start>=seg.offset && isValidChar(seg.array[start])) { while (start >= seg.offset && isValidChar(seg.array[start])) {
start--; start--;
} }
start++; start++;
len = segEnd - start; len = segEnd - start;
return len==0 ? EMPTY_STRING : new String(seg.array, start, len); return len == 0 ? EMPTY_STRING : new String(seg.array, start, len);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public List<Completion> getCompletionsAt(JTextComponent tc, Point p) { public List<Completion> getCompletionsAt(JTextComponent tc, Point p) {
int offset = tc.viewToModel(p); int offset = tc.viewToModel(p);
if (offset<0 || offset>=tc.getDocument().getLength()) { if (offset < 0 || offset >= tc.getDocument().getLength()) {
lastCompletionsAtText = null; lastCompletionsAtText = null;
return lastParameterizedCompletionsAt = null; return lastParameterizedCompletionsAt = null;
} }
Segment s = new Segment(); Segment s = new Segment();
Document doc = tc.getDocument(); Document doc = tc.getDocument();
Element root = doc.getDefaultRootElement(); Element root = doc.getDefaultRootElement();
int line = root.getElementIndex(offset); int line = root.getElementIndex(offset);
Element elem = root.getElement(line); Element elem = root.getElement(line);
int start = elem.getStartOffset(); int start = elem.getStartOffset();
int end = elem.getEndOffset() - 1; int end = elem.getEndOffset() - 1;
try { try {
doc.getText(start, end-start, s); doc.getText(start, end - start, s);
// Get the valid chars before the specified offset. // Get the valid chars before the specified offset.
int startOffs = s.offset + (offset-start) - 1; int startOffs = s.offset + (offset - start) - 1;
while (startOffs>=s.offset && isValidChar(s.array[startOffs])) { while (startOffs >= s.offset && isValidChar(s.array[startOffs])) {
startOffs--; startOffs--;
} }
// Get the valid chars at and after the specified offset. // Get the valid chars at and after the specified offset.
int endOffs = s.offset + (offset-start); int endOffs = s.offset + (offset - start);
while (endOffs<s.offset+s.count && isValidChar(s.array[endOffs])) { while (endOffs < s.offset + s.count && isValidChar(s.array[endOffs])) {
endOffs++; endOffs++;
} }
int len = endOffs - startOffs - 1; int len = endOffs - startOffs - 1;
if (len<=0) { if (len <= 0) {
return lastParameterizedCompletionsAt = null; return lastParameterizedCompletionsAt = null;
} }
String text = new String(s.array, startOffs+1, len); String text = new String(s.array, startOffs + 1, len);
if (text.equals(lastCompletionsAtText)) { if (text.equals(lastCompletionsAtText)) {
return lastParameterizedCompletionsAt; return lastParameterizedCompletionsAt;
} }
// Get a list of all Completions matching the text. // Get a list of all Completions matching the text.
List<Completion> list = getCompletionByInputText(text); List<Completion> list = getCompletionByInputText(text);
lastCompletionsAtText = text; lastCompletionsAtText = text;
return lastParameterizedCompletionsAt = list; return lastParameterizedCompletionsAt = list;
} catch (BadLocationException ble) { } catch (BadLocationException ble) {
// Never happens // Never happens
} }
lastCompletionsAtText = null; lastCompletionsAtText = null;
return lastParameterizedCompletionsAt = null; return lastParameterizedCompletionsAt = null;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public List<ParameterizedCompletion> getParameterizedCompletions( public List<ParameterizedCompletion> getParameterizedCompletions(
JTextComponent tc) { JTextComponent tc) {
List<ParameterizedCompletion> list = null; List<ParameterizedCompletion> list = null;
// If this provider doesn't support parameterized completions, // If this provider doesn't support parameterized completions,
// bail out now. // bail out now.
char paramListStart = getParameterListStart(); char paramListStart = getParameterListStart();
if (paramListStart==0) { if (paramListStart == 0) {
return list; // null return list; // null
} }
int dot = tc.getCaretPosition(); int dot = tc.getCaretPosition();
Segment s = new Segment(); Segment s = new Segment();
Document doc = tc.getDocument(); Document doc = tc.getDocument();
Element root = doc.getDefaultRootElement(); Element root = doc.getDefaultRootElement();
int line = root.getElementIndex(dot); int line = root.getElementIndex(dot);
Element elem = root.getElement(line); Element elem = root.getElement(line);
int offs = elem.getStartOffset(); int offs = elem.getStartOffset();
int len = dot - offs - 1/*paramListStart.length()*/; int len = dot - offs - 1/*paramListStart.length()*/;
if (len<=0) { // Not enough chars on line for a method. if (len <= 0) { // Not enough chars on line for a method.
return list; // null return list; // null
} }
try { try {
doc.getText(offs, len, s); doc.getText(offs, len, s);
// Get the identifier preceding the '(', ignoring any whitespace // Get the identifier preceding the '(', ignoring any whitespace
// between them. // between them.
offs = s.offset + len - 1; offs = s.offset + len - 1;
while (offs>=s.offset && Character.isWhitespace(s.array[offs])) { while (offs >= s.offset && Character.isWhitespace(s.array[offs])) {
offs--; offs--;
} }
int end = offs; int end = offs;
while (offs>=s.offset && isValidChar(s.array[offs])) { while (offs >= s.offset && isValidChar(s.array[offs])) {
offs--; offs--;
} }
String text = new String(s.array, offs+1, end-offs); String text = new String(s.array, offs + 1, end - offs);
// Get a list of all Completions matching the text, but then // Get a list of all Completions matching the text, but then
// narrow it down to just the ParameterizedCompletions. // narrow it down to just the ParameterizedCompletions.
List<Completion> l = getCompletionByInputText(text); List<Completion> l = getCompletionByInputText(text);
if (l!=null && !l.isEmpty()) { if (l != null && !l.isEmpty()) {
for (int i=0; i<l.size(); i++) { for (int i = 0; i < l.size(); i++) {
Object o = l.get(i); Object o = l.get(i);
if (o instanceof ParameterizedCompletion) { if (o instanceof ParameterizedCompletion) {
if (list==null) { if (list == null) {
list = new ArrayList<ParameterizedCompletion>(1); list = new ArrayList<ParameterizedCompletion>(1);
} }
list.add((ParameterizedCompletion)o); list.add((ParameterizedCompletion) o);
} }
} }
} }
} catch (BadLocationException ble) { } catch (BadLocationException ble) {
// Never happens // Never happens
} }
return list; return list;
} }
/** /**
* Initializes this completion provider. * Initializes this completion provider.
*/ */
protected void init() { protected void init() {
completions = new ArrayList<Completion>(); completions = new ArrayList<Completion>();
seg = new Segment(); seg = new Segment();
} }
/** /**
* Returns whether the specified character is valid in an auto-completion. * Returns whether the specified character is valid in an auto-completion.
* The default implementation is equivalent to * The default implementation is equivalent to
* "<code>Character.isLetterOrDigit(ch) || ch=='_'</code>". Subclasses * "<code>Character.isLetterOrDigit(ch) || ch=='_'</code>". Subclasses
* can override this method to change what characters are matched. * can override this method to change what characters are matched.
* *
* @param ch The character. * @param ch The character.
* @return Whether the character is valid. * @return Whether the character is valid.
*/ */
protected boolean isValidChar(char ch) { protected boolean isValidChar(char ch) {
return Character.isLetterOrDigit(ch) || ch=='_'; return Character.isLetterOrDigit(ch) || ch == '_';
} }
/** /**
* Loads completions from an XML file. The XML should validate against * Loads completions from an XML file. The XML should validate against
* <code>CompletionXml.dtd</code>. * <code>CompletionXml.dtd</code>.
* *
* @param file An XML file to load from. * @param file An XML file to load from.
* @throws IOException If an IO error occurs. * @throws IOException If an IO error occurs.
*/ */
public void loadFromXML(File file) throws IOException { public void loadFromXML(File file) throws IOException {
BufferedInputStream bin = new BufferedInputStream( BufferedInputStream bin = new BufferedInputStream(
new FileInputStream(file)); new FileInputStream(file));
try { try {
loadFromXML(bin); loadFromXML(bin);
} finally { } finally {
bin.close(); bin.close();
} }
} }
/** /**
* Loads completions from an XML input stream. The XML should validate * Loads completions from an XML input stream. The XML should validate
* against <code>CompletionXml.dtd</code>. * against <code>CompletionXml.dtd</code>.
* *
* @param in The input stream to read from. * @param in The input stream to read from.
* @throws IOException If an IO error occurs. * @throws IOException If an IO error occurs.
*/ */
public void loadFromXML(InputStream in) throws IOException { public void loadFromXML(InputStream in) throws IOException {
loadFromXML(in, null); loadFromXML(in, null);
} }
/** /**
* Loads completions from an XML input stream. The XML should validate * Loads completions from an XML input stream. The XML should validate
* against <code>CompletionXml.dtd</code>. * against <code>CompletionXml.dtd</code>.
* *
* @param in The input stream to read from. * @param in The input stream to read from.
* @param cl The class loader to use when loading any extra classes defined * @param cl The class loader to use when loading any extra classes defined
* in the XML, such as custom {@link FunctionCompletion}s. This * in the XML, such as custom {@link FunctionCompletion}s. This
* may be <code>null</code> if the default is to be used, or if no * may be <code>null</code> if the default is to be used, or if no
* custom completions are defined in the XML. * custom completions are defined in the XML.
* @throws IOException If an IO error occurs. * @throws IOException If an IO error occurs.
*/ */
public void loadFromXML(InputStream in, ClassLoader cl) throws IOException { public void loadFromXML(InputStream in, ClassLoader cl) throws IOException {
//long start = System.currentTimeMillis(); //long start = System.currentTimeMillis();
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true); try {
CompletionXMLParser handler = new CompletionXMLParser(this, cl); factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
BufferedInputStream bin = new BufferedInputStream(in); factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
try { factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser saxParser = factory.newSAXParser(); factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
saxParser.parse(bin, handler); } catch (ParserConfigurationException | SAXNotSupportedException | SAXNotRecognizedException e) {
List<Completion> completions = handler.getCompletions(); FineLoggerFactory.getLogger().warn(e.getMessage(), e);
addCompletions(completions); }
char startChar = handler.getParamStartChar();
if (startChar!=0) { factory.setValidating(true);
char endChar = handler.getParamEndChar(); CompletionXMLParser handler = new CompletionXMLParser(this, cl);
String sep = handler.getParamSeparator(); BufferedInputStream bin = new BufferedInputStream(in);
if (endChar!=0 && sep!=null && sep.length()>0) { // Sanity try {
setParameterizedCompletionParams(startChar, sep, endChar); SAXParser saxParser = factory.newSAXParser();
} saxParser.parse(bin, handler);
} List<Completion> completions = handler.getCompletions();
} catch (SAXException se) { addCompletions(completions);
throw new IOException(se.toString()); char startChar = handler.getParamStartChar();
} catch (ParserConfigurationException pce) { if (startChar != 0) {
throw new IOException(pce.toString()); char endChar = handler.getParamEndChar();
} finally { String sep = handler.getParamSeparator();
//long time = System.currentTimeMillis() - start; if (endChar != 0 && sep != null && sep.length() > 0) { // Sanity
//System.out.println("XML loaded in: " + time + "ms"); setParameterizedCompletionParams(startChar, sep, endChar);
bin.close(); }
} }
} catch (SAXException se) {
} throw new IOException(se.toString());
} catch (ParserConfigurationException pce) {
throw new IOException(pce.toString());
/** } finally {
* Loads completions from an XML file. The XML should validate against //long time = System.currentTimeMillis() - start;
* <code>CompletionXml.dtd</code>. //System.out.println("XML loaded in: " + time + "ms");
* bin.close();
* @param resource A resource the current ClassLoader can get to. }
* @throws IOException If an IO error occurs.
*/ }
public void loadFromXML(String resource) throws IOException {
ClassLoader cl = getClass().getClassLoader();
InputStream in = cl.getResourceAsStream(resource); /**
if (in==null) { * Loads completions from an XML file. The XML should validate against
File file = new File(resource); * <code>CompletionXml.dtd</code>.
if (file.isFile()) { *
in = new FileInputStream(file); * @param resource A resource the current ClassLoader can get to.
} * @throws IOException If an IO error occurs.
else { */
throw new IOException("No such resource: " + resource); public void loadFromXML(String resource) throws IOException {
} ClassLoader cl = getClass().getClassLoader();
} InputStream in = cl.getResourceAsStream(resource);
BufferedInputStream bin = new BufferedInputStream(in); if (in == null) {
try { File file = new File(resource);
loadFromXML(bin); if (file.isFile()) {
} finally { in = new FileInputStream(file);
bin.close(); } else {
} throw new IOException("No such resource: " + resource);
} }
}
BufferedInputStream bin = new BufferedInputStream(in);
try {
loadFromXML(bin);
} finally {
bin.close();
}
}
} }

4
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java

@ -624,6 +624,10 @@ public class SyntaxScheme implements Cloneable, TokenTypes {
SyntaxSchemeLoader parser = null; SyntaxSchemeLoader parser = null;
try { try {
XMLReader reader = XMLReaderFactory.createXMLReader(); XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
parser = new SyntaxSchemeLoader(baseFont); parser = new SyntaxSchemeLoader(baseFont);
parser.baseFont = baseFont; parser.baseFont = baseFont;
reader.setContentHandler(parser); reader.setContentHandler(parser);

9
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java

@ -22,6 +22,7 @@ import java.lang.reflect.Field;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
import javax.swing.text.StyleContext; import javax.swing.text.StyleContext;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParser;
@ -493,6 +494,8 @@ public class Theme {
StreamResult result = new StreamResult(new PrintWriter( StreamResult result = new StreamResult(new PrintWriter(
new UnicodeWriter(bout, "UTF-8"))); new UnicodeWriter(bout, "UTF-8")));
TransformerFactory transFac = TransformerFactory.newInstance(); TransformerFactory transFac = TransformerFactory.newInstance();
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = transFac.newTransformer(); Transformer transformer = transFac.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
@ -580,8 +583,12 @@ public class Theme {
public static void load(Theme theme, InputStream in) throws IOException { public static void load(Theme theme, InputStream in) throws IOException {
SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(true);
try { try {
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
spf.setValidating(true);
SAXParser parser = spf.newSAXParser(); SAXParser parser = spf.newSAXParser();
XMLReader reader = parser.getXMLReader(); XMLReader reader = parser.getXMLReader();
XmlHandler handler = new XmlHandler(); XmlHandler handler = new XmlHandler();

8
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java

@ -14,6 +14,7 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.parsers.*; import javax.xml.parsers.*;
import javax.xml.transform.*; import javax.xml.transform.*;
import javax.xml.transform.dom.*; import javax.xml.transform.dom.*;
@ -94,6 +95,11 @@ public class Macro {
DocumentBuilder db = null; DocumentBuilder db = null;
Document doc = null; Document doc = null;
try { try {
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
db = dbf.newDocumentBuilder(); db = dbf.newDocumentBuilder();
//InputSource is = new InputSource(new FileReader(file)); //InputSource is = new InputSource(new FileReader(file));
InputSource is = new InputSource(new UnicodeReader( InputSource is = new InputSource(new UnicodeReader(
@ -374,6 +380,8 @@ public class Macro {
StreamResult result = new StreamResult(new File(fileName)); StreamResult result = new StreamResult(new File(fileName));
DOMSource source = new DOMSource(doc); DOMSource source = new DOMSource(doc);
TransformerFactory transFac = TransformerFactory.newInstance(); TransformerFactory transFac = TransformerFactory.newInstance();
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = transFac.newTransformer(); Transformer transformer = transFac.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, FILE_ENCODING); transformer.setOutputProperty(OutputKeys.ENCODING, FILE_ENCODING);

5
designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java

@ -12,6 +12,7 @@ import com.fr.third.springframework.web.context.support.AnnotationConfigWebAppli
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import org.apache.catalina.Context; import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.StandardRoot; import org.apache.catalina.webresources.StandardRoot;
@ -73,6 +74,10 @@ public class FineEmbedServerActivator extends Activator {
String contextPath = "/" + ProductConstants.getAppFolderName(); String contextPath = "/" + ProductConstants.getAppFolderName();
final Context context = tomcat.addContext(contextPath, docBase); final Context context = tomcat.addContext(contextPath, docBase);
context.setResources(new StandardRoot(context)); context.setResources(new StandardRoot(context));
Wrapper servlet = Tomcat.addServlet(context, "DruidStatView", "com.fr.third.alibaba.druid.support.http.StatViewServlet");
context.addServletMappingDecoded("/druid/*", "DruidStatView");
servlet.setLoadOnStartup(1);
servlet.setOverridable(true);
Tomcat.initWebappDefaults(context); Tomcat.initWebappDefaults(context);
//覆盖tomcat的WebAppClassLoader //覆盖tomcat的WebAppClassLoader
context.setLoader(new FRTomcatLoader()); context.setLoader(new FRTomcatLoader());

Loading…
Cancel
Save