Added: incubator/jdo/trunk/ri11/maven.xml
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/maven.xml?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/maven.xml (added)
+++ incubator/jdo/trunk/ri11/maven.xml Fri Mar 18 17:02:29 2005
@@ -0,0 +1,371 @@
+
+
+
+
This interface is specific to Forte for Java, version 3.0, + * and is subject to change without notice. In particular, as additional + * experience is gained with specific application servers, this interface + * may have methods added and removed, even with patch releases. + * Therefore, this interface should be considered very volatile, and + * any class that implements it might have to be reimplemented whenever + * an upgrade to either the application server or Forte for Java occurs.
+ * The class that implements this interface must register itself + * by a static method at class initialization time. For example, + *+ * + * @author Marina Vatkina + */ +public interface EJBHelper { + + /** Returns the UserTransaction associated with the calling thread. If there + * is no transaction currently in progress, this method returns null. + * @return the UserTransaction instance for the calling thread + */ + UserTransaction getUserTransaction(); + + /** Identify the Transaction context for the calling thread, and return a + * Transaction instance that can be used to register synchronizations, + * and used as the key for HashMaps. The returned Transaction must implement + *+ * import org.apache.jdo.*; + * class blackHerringEJBImplHelper implements EJBHelper { + * static EJBHelper.register(new blackHerringEJBImplHelper()); + * ... + * } + *
equals()
and hashCode()
based on the global transaction id.
+ * All Transaction instances returned by this method called in the same + * Transaction context must compare equal and return the same hashCode. + * The Transaction instance returned will be held as the key to an + * internal HashMap until the Transaction completes. If there is no transaction + * associated with the current thread, this method returns null. + * @return the Transaction instance for the calling thread + */ + Transaction getTransaction(); + + /** Translate local representation of the Transaction Status to + * javax.transaction.Status value if necessary. Otherwise this method + * should return the value passed to it as an argument. + *
This method is used during afterCompletion callbacks to translate
+ * the parameter value passed by the application server to the
+ * afterCompletion method. The return value must be one of:
+ * javax.transaction.Status.STATUS_COMMITTED
or
+ * javax.transaction.Status.STATUS_ROLLED_BACK
.
+ * @param st local Status value
+ * @return the javax.transaction.Status value of the status
+ */
+ int translateStatus(int st);
+
+ /** Replace newly created instance of internal PersistenceManagerFactory
+ * with the hashed one if it exists. The replacement is necessary only if
+ * the JNDI lookup always returns a new instance. Otherwise this method
+ * returns the object passed to it as an argument.
+ *
+ * PersistenceManagerFactory is uniquely identified by
+ * ConnectionFactory.hashCode() if ConnectionFactory is
+ * not null; otherwise by ConnectionFactoryName.hashCode() if
+ * ConnectionFactoryName is not null; otherwise
+ * by the combination of URL.hashCode() + userName.hashCode() +
+ * password.hashCode() + driverName.hashCode();
+ *
+ * @param pmf PersistenceManagerFactory instance to be replaced
+ * @return the PersistenceManagerFactory known to the runtime
+ */
+ PersistenceManagerFactory replacePersistenceManagerFactory(
+ PersistenceManagerFactory pmf) ;
+
+ /** Called at the beginning of the Transaction.beforeCompletion() to
+ * register the component with the app server if necessary.
+ * The component argument is an array of Objects.
+ * The first element is javax.jdo.Transaction object responsible for
+ * transaction completion.
+ * The second element is javax.jdo.PersistenceManager object that has
+ * been associated with the Transaction context for the calling thread.
+ * The third element is javax.transaction.Transaction object that has been
+ * associated with the given instance of PersistenceManager.
+ * The return value is passed unchanged to the postInvoke method.
+ *
+ * @param component an array of Objects
+ * @return implementation-specific Object
+ */
+ Object enlistBeforeCompletion(Object component) ;
+
+ /** Called at the end of the Transaction.beforeCompletion() to
+ * de-register the component with the app server if necessary.
+ * The parameter is the return value from preInvoke, and can be any
+ * Object.
+ *
+ * @param im implementation-specific Object
+ */
+ void delistBeforeCompletion(Object im) ;
+
+}
+
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/EJBImplHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/EJBImplHelper.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/EJBImplHelper.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/EJBImplHelper.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * EJBImplHelper.java
+ *
+ * Created on December 15, 2000, 10:15 AM
+ */
+package org.apache.jdo.ejb;
+
+import javax.transaction.*;
+
+import javax.jdo.PersistenceManagerFactory;
+
+/** Provides helper methods for a Forte for Java implementation with the
+ * application server specific information in the distributed transaction
+ * environment. Calls corresponding methods on the registered class which
+ * implements EJBHelper interface.
+ *
+ * @author Marina Vatkina
+ */
+public class EJBImplHelper {
+
+ /** Reference to a class that implements EJBHelper interface for this
+ * particular application server
+ */
+ static EJBHelper myHelper;
+
+ /** Register class that implements EJBHelper interface
+ * Should be called by a static method at class initialization time.
+ *
+ * @param h application server specific implemetation of the
+ * EJBHelper interface.
+ */
+ public static void registerEJBHelper (EJBHelper h) {
+ myHelper = h;
+ }
+
+ /** Returns Transaction instance that can be used to register
+ * synchronizations. In a non-managed environment or if there is no
+ * transaction associated with the current thread, this method
+ * returns null.
+ *
+ * @see EJBHelper#getTransaction()
+ * @return the Transaction instance for the calling thread
+ */
+ public static Transaction getTransaction() {
+ return myHelper == null ? null : myHelper.getTransaction();
+ }
+
+ /** Returns the UserTransaction associated with the calling thread.
+ * In a non-managed environment or if there is no transaction
+ * currently in progress, this method returns null.
+ *
+ * @see EJBHelper#getUserTransaction()
+ * @return the UserTransaction instance for the calling thread
+ */
+ public static UserTransaction getUserTransaction() {
+ return myHelper == null ? null : myHelper.getUserTransaction();
+ }
+
+ /** Identifies the managed environment behavior.
+ * @return true if there is a helper class registered.
+ */
+ public static boolean isManaged() {
+ return myHelper != null;
+ }
+
+ /** Translates local representation of the Transaction Status to
+ * javax.transaction.Status value. In a non-managed environment
+ * returns the value passed to it as an argument.
+ *
+ * @see EJBHelper#translateStatus(int st)
+ * @param st Status value
+ * @return the javax.transaction.Status value of the status
+ */
+ public static int translateStatus(int st) {
+ return myHelper == null ? st : myHelper.translateStatus(st);
+ }
+
+ /** Returns the hashed instance of internal PersistenceManagerFactory
+ * that compares equal to the newly created instance or the instance
+ * itself if it is not found. In a non-managed environment returns
+ * the value passed to it as an argument.
+ *
+ * @see EJBHelper#replacePersistenceManagerFactory(
+ * PersistenceManagerFactory pmf)
+ * @param pmf PersistenceManagerFactory instance to be replaced
+ * @return the PersistenceManagerFactory known to the runtime
+ */
+ public static PersistenceManagerFactory replacePersistenceManagerFactory(
+ PersistenceManagerFactory pmf) {
+ return myHelper == null ? pmf :
+ myHelper.replacePersistenceManagerFactory(pmf);
+ }
+
+ /** Called at the beginning of the Transaction.beforeCompletion()
+ * to register the component with the app server if necessary. In a
+ * non-managed environment or if the delistBeforeCompletion method
+ * does not use the value, this method returns null.
+ *
+ * @see EJBHelper#enlistBeforeCompletion(Object component)
+ * @param component an array of Objects
+ * @return implementation-specific Object
+ */
+ public static Object enlistBeforeCompletion(Object component) {
+ return myHelper == null ? null :
+ myHelper.enlistBeforeCompletion(component);
+ }
+
+ /** Called a non-managed environment at the end of the
+ * Transaction.beforeCompletion() to de-register the component with
+ * the app server if necessary.
+ *
+ * @see EJBHelper#delistBeforeCompletion(Object im)
+ * @param im implementation-specific Object
+ */
+ public static void delistBeforeCompletion(Object im) {
+ if (myHelper != null) {
+ myHelper.delistBeforeCompletion(im);
+ }
+ }
+
+}
+
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/package.html
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/package.html?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/package.html (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/ejb/package.html Fri Mar 18 17:02:29 2005
@@ -0,0 +1,26 @@
+
+
+
+
This package contains classes and interfaces for EJB support.
+ + Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/EnhancerMain.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/EnhancerMain.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/EnhancerMain.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/EnhancerMain.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,387 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.enhancer; + +import java.io.IOException; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.PrintWriter; + +import java.util.List; +import java.util.Iterator; +import java.util.Properties; + +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import org.apache.jdo.impl.enhancer.ClassFileEnhancer; +import org.apache.jdo.impl.enhancer.ClassFileEnhancerHelper; +import org.apache.jdo.impl.enhancer.ClassFileEnhancerTimer; +import org.apache.jdo.impl.enhancer.EnhancerFatalError; +import org.apache.jdo.impl.enhancer.EnhancerOptions; +import org.apache.jdo.impl.enhancer.EnhancerUserException; +import org.apache.jdo.impl.enhancer.JdoMetaMain; +import org.apache.jdo.impl.enhancer.OutputStreamWrapper; +import org.apache.jdo.impl.enhancer.core.EnhancerFilter; + + + +/** + * JDO command line enhancer. + * + * @author Martin Zaun + */ +public class EnhancerMain + extends JdoMetaMain +{ + /** + * The options and arguments. + */ + protected EnhancerOptions options; + + /** + * The byte code enhancer. + */ + protected ClassFileEnhancer enhancer; + + /** + * Creates an instance. + */ + public EnhancerMain(PrintWriter out, + PrintWriter err) + { + this(out, err, new EnhancerOptions(out, err)); + } + + /** + * Creates an instance. + */ + public EnhancerMain(PrintWriter out, + PrintWriter err, + EnhancerOptions options) + { + super(out, err, options); + this.options = options; + } + + // ---------------------------------------------------------------------- + + /** + * Enhances all files entered in the command line. + * + * @param classNames List of class names. + * @param classFileNames List of class file names. + * @param archiveFileNames List of archive file names. + */ + private int enhanceInputFiles(List classNames, + List classFileNames, + List archiveFileNames) + { + int res = 0; + try { + String name = null; + for (Iterator i = archiveFileNames.iterator(); i.hasNext();) { + try { + name = (String)i.next(); + enhanceArchiveFile(name); + } catch (EnhancerUserException ex) { + printlnErr("Error while enhancing " + name, ex, + options.verbose.value); + res++; + continue; + } + } + for (Iterator i = classFileNames.iterator(); i.hasNext();) { + try { + name = (String)i.next(); + enhanceClassFile(openFileInputStream(name)); + } catch (EnhancerUserException ex) { + printlnErr("Error while enhancing " + name, ex, + options.verbose.value); + res++; + continue; + } + } + for (Iterator i = classNames.iterator(); i.hasNext();) { + try { + name = (String)i.next(); + enhanceClassFile(openClassInputStream(name)); + } catch (EnhancerUserException ex) { + printlnErr("Error while enhancing " + name, ex, + options.verbose.value); + res++; + continue; + } + } + } catch (IOException ex) { + printlnErr("IO Error while enhancing", ex, options.verbose.value); + return ++res; + } catch (EnhancerFatalError ex) { + // enhancer is not anymore guaranteed to be consistent + printlnErr("Fatal error while enhancing", ex, options.verbose.value); + enhancer = null; + return ++res; + } + return res; + } + + /** + * Enhances a classfile. + * + * @param in The input stream of the classfile. + */ + private void enhanceClassFile(InputStream in) + throws IOException, EnhancerUserException, EnhancerFatalError + { + OutputStream out = null; + try { + final File temp = File.createTempFile("enhancer", ".class"); + out = new BufferedOutputStream(new FileOutputStream(temp)); + + //enhance + final OutputStreamWrapper wrapper = new OutputStreamWrapper(out); + final boolean enhanced = enhancer.enhanceClassFile(in, wrapper); + + closeOutputStream(out); + out = null; + createOutputFile(enhanced, + getClassFileName(wrapper.getClassName()), temp); + } finally { + closeInputStream(in); + closeOutputStream(out); + } + } + + /** + * Enhances a archive file. + * + * @param fileName The filename of the archive file. + */ + private void enhanceArchiveFile(String fileName) + throws IOException, EnhancerUserException, EnhancerFatalError + { + ZipInputStream in = null; + ZipOutputStream out = null; + try { + final File temp = File.createTempFile("enhancer", ".zip"); + in = new ZipInputStream(new BufferedInputStream( + new FileInputStream(new File(fileName)))); + out = new ZipOutputStream(new BufferedOutputStream( + new FileOutputStream(temp))); + + // enhance the archive file + final boolean enhanced + = ClassFileEnhancerHelper.enhanceZipFile(enhancer, in, out); + + // create the output file + closeOutputStream(out); + out = null; + createOutputFile(enhanced, new File(fileName).getName(), temp); + } finally { + closeOutputStream(out); + closeInputStream(in); + } + } + + /** + * Creates a file object that represents the output archive file for + * a given archive file to enhance. + * + * @param archiveFileName the input archive file name + * @return the output archive file + */ + private File createArchiveOutputFile(String archiveFileName) + { + return new File(options.destDir.value, + new File(archiveFileName).getName()); + } + + /** + * Creates the output file for an enhanced class- or archive file. If the + * enhanced file is written back depends on the command line options. + * + * @param enhanced Has the input file been enhanced? + * @param fileName The name of the output file. + * @param temp The temp file, the output is written to. + * @exception IOException If the file could not be created. + */ + private void createOutputFile(boolean enhanced, + String fileName, + File temp) + throws IOException + { + //noWrite or (not enhanced and not forceWrite) + if (options.noWrite.value + || (!enhanced && !options.forceWrite.value)) { + temp.deleteOnExit(); + return; + } + + // create file and its parent directory + final File file = new File(options.destDir.value, fileName); + final File dir = file.getAbsoluteFile().getParentFile(); + if (!dir.exists() && !dir.mkdirs()) { + throw new IOException("Error creating directory '" + + dir.getAbsolutePath() + "'."); + } + + file.delete(); //delete old file if exists + boolean renamed = temp.renameTo(file); + if (!renamed) { + //@dave: empirical evidence shows that renameTo does not allow for + // crossing filesystem boundaries. If it fails, try "by hand". + InputStream in = null; + OutputStream out = null; + try { + in = new FileInputStream(temp); + out = new FileOutputStream(file); + int PAGESIZE = 4096; // Suggest a better size? + byte data[] = new byte[PAGESIZE]; + while (in.available() > 0) { + int numRead = in.read(data, 0, PAGESIZE); + out.write(data, 0, numRead); + } + renamed = true; + } catch (IOException ex) { + throw new IOException("Could not rename temp file '" + + temp.getAbsolutePath() + + "' to '" + file.getAbsolutePath() + + "': " + ex); + } finally { + closeInputStream(in); + closeOutputStream(out); + } + if (renamed) { + temp.delete(); //delete temporary file + } + else { + throw new IOException("Could not rename temp file '" + + temp.getAbsolutePath() + + "' to '" + file.getAbsolutePath() + "'."); + } + } + } + + /** + * Closes an output stream. + * + * @param out the output stream + */ + private void closeOutputStream(OutputStream out) + { + if (out != null) { + try { + out.close(); + } catch (IOException ex) { + printlnErr("", ex, options.verbose.value); + } + } + } + + // ---------------------------------------------------------------------- + + /** + * Initializes all components. + */ + protected void init() + throws EnhancerFatalError, EnhancerUserException + { + super.init(); + + final Properties props = new Properties(); + if (options.verbose.value) { + props.put(EnhancerFilter.VERBOSE_LEVEL, + EnhancerFilter.VERBOSE_LEVEL_VERBOSE); + } + + if (options.doTiming.value) { + props.put(EnhancerFilter.DO_TIMING_STATISTICS, + Boolean.TRUE.toString()); + } + + if (options.dumpClass.value) { + props.put(EnhancerFilter.DUMP_CLASS, + Boolean.TRUE.toString()); + } + + if (options.noAugment.value) { + props.put(EnhancerFilter.NO_AUGMENT, + Boolean.TRUE.toString()); + } + + if (options.noAnnotate.value) { + props.put(EnhancerFilter.NO_ANNOTATE, + Boolean.TRUE.toString()); + } + + try { + enhancer = new EnhancerFilter(jdoMeta, props, out, err); + if (options.doTiming.value) { + // wrap with timing byte-code enhancer + enhancer = new ClassFileEnhancerTimer(enhancer); + } + } catch (EnhancerUserException ex) { + printlnErr("Error while creating the enhancer", ex, + options.verbose.value); + throw ex; + } catch (EnhancerFatalError ex) { + // enhancer is not anymore guaranteed to be consistent + printlnErr("Fatal error while creating the enhancer", ex, + options.verbose.value); + enhancer = null; + throw ex; + } catch (RuntimeException ex) { + // enhancer is not anymore guaranteed to be consistent + printlnErr("Internal error while creating the enhancer", ex, + options.verbose.value); + enhancer = null; + throw new EnhancerFatalError(ex); + } + } + + /** + * Run the enhancer. + */ + protected int process() + { + return enhanceInputFiles(options.classNames, + options.classFileNames, + options.archiveFileNames); + } + + // ---------------------------------------------------------------------- + + /** + * Runs this class + */ + static public void main(String[] args) + { + final PrintWriter out = new PrintWriter(System.out, true); + out.println("--> EnhancerMain.main()"); + //out.println("JDO RI Class-File Enhancer"); + final EnhancerMain main = new EnhancerMain(out, out); + int res = main.run(args); + //out.println("done."); + out.println("<-- EnhancerMain.main(): exit = " + res); + System.exit(res); + } +}