--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.services.stream.SingleStream\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.services.stream;\r
+\r
+import org.apache.derby.iapi.services.stream.InfoStreams;\r
+import org.apache.derby.iapi.services.stream.HeaderPrintWriter;\r
+import org.apache.derby.iapi.services.stream.PrintWriterGetHeader;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.monitor.ModuleControl;\r
+import org.apache.derby.iapi.services.monitor.ModuleSupportable;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+\r
+import org.apache.derby.iapi.reference.Property;\r
+import org.apache.derby.iapi.services.property.PropertyUtil;\r
+\r
+import java.io.BufferedOutputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.io.File;\r
+import java.io.Writer;\r
+\r
+import java.util.Properties;\r
+\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Modifier;\r
+import java.lang.reflect.Member;\r
+import java.lang.reflect.InvocationTargetException;\r
+\r
+/**\r
+ *\r
+ * The Basic Services provide InfoStreams for reporting\r
+ * information. Two streams are provided: trace and error.\r
+ * It is configurable where these streams are directed.\r
+ * <p>\r
+ * Errors will be printed to the error stream in addition\r
+ * to being sent to the client.\r
+ * <p>\r
+ * By default both streams are sent to an error log\r
+ * for the system. When creating a message for a stream,\r
+ * you can create an initial entry with header information\r
+ * and then append to it as many times as desired.\r
+ * <p>\r
+ * Note: if character encodings are needed, the use of\r
+ * java.io.*OutputStream's should be replaced with\r
+ * java.io.*Writer's (assuming the Writer interface\r
+ * remains stable in JDK1.1)\r
+ *\r
+ */\r
+public final class SingleStream\r
+implements InfoStreams, ModuleControl, java.security.PrivilegedAction\r
+{\r
+\r
+ /*\r
+ ** Instance fields\r
+ */\r
+ private HeaderPrintWriter theStream;\r
+\r
+\r
+ /**\r
+ The no-arg public constructor for ModuleControl's use.\r
+ */\r
+ public SingleStream() {\r
+ }\r
+\r
+ /**\r
+ * @see org.apache.derby.iapi.services.monitor.ModuleControl#boot\r
+ */\r
+ public void boot(boolean create, Properties properties) {\r
+ theStream = makeStream();\r
+ }\r
+\r
+\r
+ /**\r
+ * @see org.apache.derby.iapi.services.monitor.ModuleControl#stop\r
+ */\r
+ public void stop() {\r
+ ((BasicHeaderPrintWriter) theStream).complete();\r
+ }\r
+\r
+ /*\r
+ * InfoStreams interface\r
+ */\r
+\r
+ /**\r
+ * @see org.apache.derby.iapi.services.stream.InfoStreams#stream\r
+ */\r
+ public HeaderPrintWriter stream() {\r
+ return theStream;\r
+ }\r
+\r
+ //\r
+ // class interface\r
+ //\r
+\r
+ /**\r
+ Make the stream; note that service properties override\r
+ application and system properties.\r
+\r
+ */\r
+ private HeaderPrintWriter makeStream() {\r
+\r
+ // get the header\r
+ PrintWriterGetHeader header = makeHeader();\r
+ HeaderPrintWriter hpw = makeHPW(header);\r
+\r
+ // If hpw == null then no properties were specified for the stream\r
+ // so use/create the default stream.\r
+ if (hpw == null)\r
+ hpw = createDefaultStream(header);\r
+ return hpw;\r
+ }\r
+\r
+ /**\r
+ Return a new header object.\r
+ */\r
+ private PrintWriterGetHeader makeHeader() {\r
+\r
+ return new BasicGetLogHeader(true, true, (String) null);\r
+ }\r
+\r
+ /**\r
+ create a HeaderPrintWriter based on the header.\r
+ Will still need to determine the target type.\r
+ */\r
+ private HeaderPrintWriter makeHPW(PrintWriterGetHeader header) {\r
+\r
+ // the type of target is based on which property is used\r
+ // to set it. choices are file, method, field, stream\r
+\r
+ String target = PropertyUtil.\r
+ getSystemProperty(Property.ERRORLOG_FILE_PROPERTY);\r
+ if (target!=null)\r
+ return makeFileHPW(target, header);\r
+\r
+ target = PropertyUtil.\r
+ getSystemProperty(Property.ERRORLOG_METHOD_PROPERTY);\r
+ if (target!=null) \r
+ return makeMethodHPW(target, header);\r
+\r
+ target = PropertyUtil.\r
+ getSystemProperty(Property.ERRORLOG_FIELD_PROPERTY);\r
+ if (target!=null) \r
+ return makeFieldHPW(target, header);\r
+\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ Make a header print writer out of a file name. If it is a relative\r
+ path name then it is taken as relative to derby.system.home if that is set,\r
+ otherwise relative to the current directory. If the path name is absolute\r
+ then it is taken as absolute.\r
+ */\r
+ private HeaderPrintWriter PBmakeFileHPW(String fileName,\r
+ PrintWriterGetHeader header) {\r
+\r
+ boolean appendInfoLog = PropertyUtil.getSystemBoolean(Property.LOG_FILE_APPEND);\r
+\r
+ File streamFile = new File(fileName);\r
+\r
+ // See if this needs to be made relative to something ...\r
+ if (!streamFile.isAbsolute()) {\r
+ Object monitorEnv = Monitor.getMonitor().getEnvironment();\r
+ if (monitorEnv instanceof File)\r
+ streamFile = new File((File) monitorEnv, fileName);\r
+ }\r
+\r
+ FileOutputStream fos;\r
+\r
+ try {\r
+\r
+ if (streamFile.exists() && appendInfoLog)\r
+ fos = new FileOutputStream(streamFile.getPath(), true);\r
+ else\r
+ fos = new FileOutputStream(streamFile);\r
+ } catch (IOException ioe) {\r
+ return useDefaultStream(header, ioe);\r
+ } catch (SecurityException se) {\r
+ return useDefaultStream(header, se);\r
+ }\r
+\r
+ return new BasicHeaderPrintWriter(new BufferedOutputStream(fos), header,\r
+ true, streamFile.getPath());\r
+ }\r
+\r
+ private HeaderPrintWriter makeMethodHPW(String methodInvocation,\r
+ PrintWriterGetHeader header) {\r
+\r
+ int lastDot = methodInvocation.lastIndexOf('.');\r
+ String className = methodInvocation.substring(0, lastDot);\r
+ String methodName = methodInvocation.substring(lastDot+1);\r
+\r
+ Throwable t;\r
+ try {\r
+ Class theClass = Class.forName(className);\r
+ //Added by Jeff Huang\r
+ //TODO: FIXIT\r
+ try {\r
+ Method theMethod = theClass.getMethod(methodName, new Class[0]);\r
+\r
+ if (!Modifier.isStatic(theMethod.getModifiers())) {\r
+ HeaderPrintWriter hpw = useDefaultStream(header);\r
+ hpw.printlnWithHeader(theMethod.toString() + " is not static");\r
+ return hpw;\r
+ }\r
+\r
+ try {\r
+ return makeValueHPW(theMethod, theMethod.invoke((Object) null, \r
+ new Object[0]), header, methodInvocation);\r
+ } catch (IllegalAccessException iae) {\r
+ t = iae;\r
+ } catch (IllegalArgumentException iarge) {\r
+ t = iarge;\r
+ } catch (InvocationTargetException ite) {\r
+ t = ite.getTargetException();\r
+ }\r
+\r
+ } catch (NoSuchMethodException nsme) {\r
+ t = nsme;\r
+ }\r
+ } catch (ClassNotFoundException cnfe) {\r
+ t = cnfe;\r
+ } catch (SecurityException se) {\r
+ t = se;\r
+ \r
+ }\r
+ return useDefaultStream(header, t);\r
+\r
+ }\r
+\r
+\r
+ private HeaderPrintWriter makeFieldHPW(String fieldAccess,\r
+ PrintWriterGetHeader header) {\r
+\r
+ int lastDot = fieldAccess.lastIndexOf('.');\r
+ String className = fieldAccess.substring(0, lastDot);\r
+ String fieldName = fieldAccess.substring(lastDot+1,\r
+ fieldAccess.length());\r
+\r
+ Throwable t;\r
+ try {\r
+ Class theClass = Class.forName(className);\r
+ //Added by Jeff Huang\r
+ //TODO: FIXIT\r
+ try {\r
+ Field theField = theClass.getField(fieldName);\r
+ \r
+ if (!Modifier.isStatic(theField.getModifiers())) {\r
+ HeaderPrintWriter hpw = useDefaultStream(header);\r
+ hpw.printlnWithHeader(theField.toString() + " is not static");\r
+ return hpw;\r
+ }\r
+\r
+ try {\r
+ return makeValueHPW(theField, theField.get((Object) null), \r
+ header, fieldAccess);\r
+ } catch (IllegalAccessException iae) {\r
+ t = iae;\r
+ } catch (IllegalArgumentException iarge) {\r
+ t = iarge;\r
+ }\r
+\r
+ } catch (NoSuchFieldException nsfe) {\r
+ t = nsfe;\r
+ }\r
+ } catch (ClassNotFoundException cnfe) {\r
+ t = cnfe;\r
+ } catch (SecurityException se) {\r
+ t = se;\r
+ }\r
+ return useDefaultStream(header, t);\r
+\r
+ /*\r
+ If we decide it is a bad idea to use reflect and need\r
+ an alternate implementation, we can hard-wire those\r
+ fields that we desire to give configurations access to,\r
+ like so:\r
+\r
+ if ("java.lang.System.out".equals(fieldAccess))\r
+ os = System.out;\r
+ else if ("java.lang.System.err".equals(fieldAccess))\r
+ os = System.err;\r
+ */\r
+ }\r
+\r
+ private HeaderPrintWriter makeValueHPW(Member whereFrom, Object value,\r
+ PrintWriterGetHeader header, String name) {\r
+\r
+ if (value instanceof OutputStream)\r
+ return new BasicHeaderPrintWriter((OutputStream) value, header, false, name);\r
+ else if (value instanceof Writer)\r
+ return new BasicHeaderPrintWriter((Writer) value, header, false, name);\r
+ \r
+ HeaderPrintWriter hpw = useDefaultStream(header);\r
+\r
+ if (value == null)\r
+ hpw.printlnWithHeader(whereFrom.toString() + "=null");\r
+ else\r
+ hpw.printlnWithHeader(whereFrom.toString() + " instanceof " + value.getClass().getName());\r
+\r
+ return hpw;\r
+ }\r
+ \r
+\r
+ /**\r
+ Used when no configuration information exists for a stream.\r
+ */\r
+ private HeaderPrintWriter createDefaultStream(PrintWriterGetHeader header) {\r
+ return makeFileHPW("derby.log", header);\r
+ }\r
+\r
+ /**\r
+ Used when creating a stream creates an error.\r
+ */\r
+ private HeaderPrintWriter useDefaultStream(PrintWriterGetHeader header) {\r
+\r
+ return new BasicHeaderPrintWriter(System.err, header, false, "System.err");\r
+ }\r
+\r
+ private HeaderPrintWriter useDefaultStream(PrintWriterGetHeader header, Throwable t) {\r
+\r
+ HeaderPrintWriter hpw = useDefaultStream(header);\r
+ hpw.printlnWithHeader(t.toString());\r
+ return hpw;\r
+ }\r
+\r
+ /*\r
+ ** Priv block code, moved out of the old Java2 version.\r
+ */\r
+\r
+ private String PBfileName;\r
+ private PrintWriterGetHeader PBheader;\r
+\r
+ private HeaderPrintWriter makeFileHPW(String fileName, PrintWriterGetHeader header)\r
+ {\r
+ this.PBfileName = fileName;\r
+ this.PBheader = header;\r
+ return (HeaderPrintWriter) java.security.AccessController.doPrivileged(this);\r
+ }\r
+\r
+\r
+ public final Object run()\r
+ {\r
+ // SECURITY PERMISSION - OP4, OP5\r
+ return PBmakeFileHPW(PBfileName, PBheader);\r
+ }\r
+}\r
+\r