001: /**
002: * Takes care of response post-processing.
003: */package com.lutris.appserver.server;
004:
005: import java.lang.reflect.Constructor;
006: import java.lang.reflect.InvocationTargetException;
007: import java.util.Vector;
008:
009: import org.enhydra.util.ResponsePostProcessor;
010: import org.enhydra.xml.io.OutputOptions;
011: import org.w3c.dom.Node;
012:
013: import com.lutris.logging.LogChannel;
014: import com.lutris.logging.Logger;
015: import com.lutris.util.Config;
016: import com.lutris.util.ConfigException;
017: import com.lutris.util.KeywordValueException;
018:
019: /**
020: * @author Slobodan Vujasinovic
021: *
022: */
023: public class ResponsePostProcessingManager {
024:
025: /**
026: * ResponsePostProcessingManager configuration prefix
027: */
028: public static final String CONFIG_PREFIX = "ResponsePostProcessor";
029:
030: /**
031: * Name of the post processing manager generated mime type
032: */
033: private String outMimeType = "text/html";
034:
035: /**
036: * LogChannel used by ResponsePostProcessingManager
037: */
038: private LogChannel logChannel;
039:
040: /**
041: * Vector containing registered postprocessor implementations for
042: * corresponding application.
043: */
044: private Vector postProcessors;
045:
046: /**
047: * Response post-processing profiling level
048: *
049: * Negative - profile everything
050: * Zero - profile nothing
051: * Positive - profile only processing that lasted longer
052: * than specified number of milliseconds
053: */
054: private int profileLevel = 0;
055:
056: /**
057: * To do profiling or not
058: */
059: private boolean doProfile = false;
060:
061: /**
062: * Initialize post-processing manager according to application
063: * configuration!
064: *
065: * @param config
066: */
067: public ResponsePostProcessingManager(Config config,
068: LogChannel logChannel) {
069: this .logChannel = logChannel;
070: postProcessors = new Vector();
071: try {
072: // Profiling Initialization
073: profileLevel = config.getInt("TimeProfiler", 0);
074: if (profileLevel != 0) {
075: doProfile = true;
076: }
077:
078: String[] ppNames = config.getStrings("Names", null);
079: if (ppNames != null) {
080: for (int i = 0; i < ppNames.length; i++) {
081: Config ppConfig = null;
082: try {
083: ppConfig = config.getConfig(ppNames[i]);
084: if (config.getConfigFile() != null
085: && ppConfig != null)
086: ppConfig.setConfigFile(config
087: .getConfigFile());
088: } catch (KeywordValueException kwe) {
089: kwe.printStackTrace();
090: }
091: if (ppConfig != null) {
092: String ppClassName = ppConfig.getString(
093: "Class", null);
094: if (ppClassName != null) {
095: Class ppClass = null;
096: try {
097: ppClass = Class.forName(ppClassName);
098: } catch (ClassNotFoundException cnf) {
099: cnf.printStackTrace();
100: }
101: if (ppClass != null) {
102: Class[] ArgClassArray = new Class[] {};
103: Object[] ArgObject = new Object[] {};
104:
105: Constructor ppConstructor = null;
106: try {
107: ppConstructor = ppClass
108: .getDeclaredConstructor(ArgClassArray);
109: } catch (NoSuchMethodException nsm) {
110: nsm.printStackTrace();
111: }
112: if (ppConstructor != null) {
113: ResponsePostProcessor rPP = null;
114: try {
115: rPP = (ResponsePostProcessor) (ppConstructor
116: .newInstance(ArgObject));
117: rPP.setName(ppNames[i]);
118: rPP.setLogChannel(logChannel);
119: } catch (InstantiationException ie) {
120: ie.printStackTrace();
121: } catch (InvocationTargetException ite) {
122: ite.printStackTrace();
123: } catch (IllegalAccessException iae) {
124: iae.printStackTrace();
125: }
126: if (rPP != null) {
127: rPP.configure(ppConfig);
128: postProcessors.add(rPP);
129: }
130: }
131: }
132: }
133: }
134: }
135: }
136: } catch (ConfigException ce) {
137: if (logChannel != null) {
138: logChannel
139: .write(Logger.ERROR,
140: "Problem with ResponsePostProcessing initialization!");
141: }
142: ce.printStackTrace();
143: }
144: }
145:
146: /**
147: * Manages response preprocessing.
148: *
149: * @param props
150: * @param document
151: */
152: public Node manage(OutputOptions oo, Node document) {
153: if (logChannel != null) {
154: logChannel.write(Logger.DEBUG,
155: "Managing response post-processing!");
156: }
157:
158: for (int i = 0; i < postProcessors.size(); i++) {
159: ResponsePostProcessor rPP = (ResponsePostProcessor) postProcessors
160: .get(i);
161:
162: if (rPP.shouldProcess(oo.getMIMEType())) {
163: rPP = (ResponsePostProcessor) rPP.clone();
164:
165: // Start Profiling Time
166: long processingTime = startProfiler();
167:
168: document = rPP.process(oo, document);
169:
170: // End Profiling Time
171: stopProfiler(processingTime, rPP.getName());
172: }
173: }
174: return document;
175: }
176:
177: private long startProfiler() {
178: return doProfile ? System.currentTimeMillis() : -1;
179: }
180:
181: private void stopProfiler(long processingTime, String name) {
182: if (doProfile) {
183: processingTime = System.currentTimeMillis()
184: - processingTime;
185: if (processingTime > profileLevel) {
186: if (logChannel != null) {
187: logChannel
188: .write(
189: Logger.WARNING,
190: "ResponsePostProcessor "
191: + name
192: + " took "
193: + processingTime
194: + " milliseconds for response processing!");
195: }
196: }
197: }
198: }
199:
200: /**
201: * Manages response preprocessing.
202: *
203: * @param props
204: * @param byteArray
205: */
206: public byte[] manage(byte[] byteArray, String mimeEncoding,
207: String mimeType) {
208: if (logChannel != null) {
209: logChannel.write(Logger.DEBUG,
210: "Managing response post-processing!");
211: }
212:
213: outMimeType = mimeType;
214:
215: for (int i = 0; i < postProcessors.size(); i++) {
216: ResponsePostProcessor rPP = (ResponsePostProcessor) postProcessors
217: .get(i);
218:
219: if (rPP.shouldProcess(mimeType)) {
220: rPP = (ResponsePostProcessor) rPP.clone();
221: byteArray = rPP.process(byteArray, mimeEncoding,
222: mimeType);
223: outMimeType = rPP.getOutputMimeType();
224: }
225: }
226: return byteArray;
227: }
228:
229: public boolean addPostProcessor(int position,
230: ResponsePostProcessor rPP) {
231: if (position >= 0) {
232: postProcessors.add(position, rPP);
233: if (logChannel != null) {
234: logChannel.write(Logger.INFO,
235: "New ResponsePostProcessor introduced!");
236: }
237: } else {
238: return postProcessors.add(rPP);
239: }
240: return true;
241: }
242:
243: public boolean removePostProcessor(int position) {
244: if (position >= 0) {
245: postProcessors.removeElementAt(position);
246: if (logChannel != null) {
247: logChannel.write(Logger.INFO,
248: "ResponsePostProcessor removed!");
249: }
250: } else {
251: return false;
252: }
253: return true;
254: }
255:
256: public boolean removePostProcessor(ResponsePostProcessor rPP) {
257: return postProcessors.removeElement(rPP);
258: }
259:
260: public boolean removePostProcessor(String ppName) {
261: if (ppName != null) {
262: for (int i = 0; i < postProcessors.size(); i++) {
263: if (ppName
264: .equals(((ResponsePostProcessor) postProcessors
265: .elementAt(i)).getName())) {
266: postProcessors.removeElementAt(i);
267: return true;
268: }
269: }
270: }
271: return false;
272:
273: }
274:
275: public String getOutputMimeType() {
276: return this .outMimeType;
277: }
278:
279: public Vector getPostProcessors() {
280: return postProcessors;
281: }
282:
283: public void setPostProcessors(Vector postProcessors) {
284: try {
285: for (int i = 0; i < postProcessors.size(); i++) {
286: ResponsePostProcessor pp = (ResponsePostProcessor) postProcessors
287: .elementAt(i);
288: }
289: this .postProcessors = postProcessors;
290: } catch (Exception ex) {
291: // in case of exception - do nothing
292: if (logChannel != null) {
293: logChannel
294: .write(Logger.ERROR,
295: "Problem occurred during post-processor vector acceptance!");
296: }
297: ex.printStackTrace();
298: }
299: }
300:
301: }
|