openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ppod...@apache.org
Subject svn commit: r988644 [3/3] - in /openjpa/trunk/openjpa-examples/opentrader: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/openjpa/ src/main/java/org/apache/openjpa/trader/ src/main/java/org/apache...
Date Tue, 24 Aug 2010 18:11:27 GMT
Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/LongId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/LongId.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/LongId.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/LongId.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.util;
+
+
+/**
+ * {@link OpenJPAId} subclass appropriate for long fields.
+ *
+ * @author Steve Kim
+ */
+public final class LongId extends OpenJPAId {
+
+    private final long key;
+
+    public LongId() {
+        key = 0;
+    }
+    
+    public LongId(Class cls, Long key) {
+        this(cls, (key == null) ? 0L : key.longValue());
+    }
+
+    public LongId(Class cls, String key) {
+        this(cls, (key == null) ? 0L : Long.parseLong(key));
+    }
+
+    public LongId(Class cls, long key) {
+        super(cls);
+        this.key = key;
+    }
+
+    public LongId(Class cls, long key, boolean subs) {
+        super(cls, subs);
+        this.key = key;
+    }
+
+    public long getId() {
+        return key;
+    }
+
+    public Object getIdObject() {
+        return key;
+    }
+    
+    public String toString() {
+        return String.valueOf(key);
+    }
+
+    protected int idHash() {
+        return (int) (key ^ (key >>> 32));
+    }
+
+    protected boolean idEquals(OpenJPAId o) {
+        return key == ((LongId) o).key;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/LongId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/OpenJPAId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/OpenJPAId.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/OpenJPAId.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/OpenJPAId.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.util;
+
+import java.io.Serializable;
+
+import java.util.HashMap;
+/**
+ * Identity class extended by built-in OpenJPA identity objects.
+ *
+ * @author Steve Kim
+ */
+@SuppressWarnings("serial")
+public abstract class OpenJPAId
+    implements Comparable, Serializable {
+    public static final char TYPE_VALUE_SEP = '-';
+    
+    // cache the types' generated hash codes
+    private static HashMap _typeCache = new HashMap();
+
+    protected Class type;
+    protected boolean subs = true;
+
+    // type hash is based on the least-derived non-object class so that
+    // user-given ids with non-exact types match ids with exact types
+    private transient int _typeHash = 0;
+
+    protected OpenJPAId() {
+    }
+
+    protected OpenJPAId(Class type) {
+        this.type = type;
+    }
+
+    protected OpenJPAId(Class type, boolean subs) {
+        this.type = type;
+        this.subs = subs;
+    }
+
+    /**
+     * Return the persistent class which this id instance represents.
+     */
+    public Class getType() {
+        return type;
+    }
+
+    /**
+     * Whether this oid might be for a subclass of the given type.
+     * Defaults to true.
+     */
+    public boolean hasSubclasses() {
+        return subs;
+    }
+
+    /**
+     * Set the exact type of the described instance once it is known.
+     */
+    public void setManagedInstanceType(Class type) {
+        setManagedInstanceType(type, false);
+    }
+
+    /**
+     * Set the exact type of the described instance once it is known.
+     */
+    public void setManagedInstanceType(Class type, boolean subs) {
+        this.type = type;
+        this.subs = subs;
+    }
+
+    /**
+     * Return the identity value as an object.
+     */
+    public abstract Object getIdObject();
+
+    /**
+     * Return the id's hash code.
+     */
+    protected abstract int idHash();
+
+    /**
+     * Compare the id to the id of the given instance.
+     */
+    protected abstract boolean idEquals(OpenJPAId other);
+
+    /**
+     * Generate the hash code for this Id.  Cache the type's generated hash code
+     * so that it doesn't have to be generated each time.
+     */
+    public int hashCode() {
+        if (_typeHash == 0) {
+            Integer typeHashInt = (Integer) _typeCache.get(type);
+            if (typeHashInt == null) {
+                Class base = type;
+                Class superclass = base.getSuperclass();
+                while (superclass != null && superclass != Object.class) {
+                    base = base.getSuperclass();
+                    superclass = base.getSuperclass();
+                }
+                _typeHash = base.hashCode();
+                _typeCache.put(type, Integer.valueOf(_typeHash));
+            } else {
+                _typeHash = typeHashInt.intValue();
+            }
+        }
+        return _typeHash ^ idHash();
+    }
+
+    public boolean equals(Object o) {
+        if (o == this)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        OpenJPAId id = (OpenJPAId) o;
+        return idEquals(id);
+        //&& (id.type.isAssignableFrom(type)
+        //    || (subs && type.isAssignableFrom(id.type)));
+    }
+
+    public String toString() {
+        return type.getName() + TYPE_VALUE_SEP + getIdObject();
+    }
+
+    public int compareTo(Object other) {
+        if (other == this)
+            return 0;
+        if (other == null)
+            return 1;
+        return ((Comparable) getIdObject()).compareTo(((OpenJPAId) other).getIdObject ());
+	}
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/override/org/apache/openjpa/util/OpenJPAId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/ExceptionAdapter.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/ExceptionAdapter.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/ExceptionAdapter.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/ExceptionAdapter.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.server;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+
+/**
+ * Adapts a server-side exception to a RuntimeException.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class ExceptionAdapter {
+    static List<String> exceptionTypes = Arrays.asList(
+            "org.apache.openjpa.persistence.PersistenceException");
+    
+
+    RuntimeException translate(Throwable t) {
+        Throwable cause = searchForKnownButNonTranslatableException(t);
+        if (cause != null) {
+            t = cause;
+        }
+        RuntimeException e = new RuntimeException(t.getMessage());
+        e.setStackTrace(t.getStackTrace());
+        return e;
+    }
+    
+    private Throwable searchForKnownButNonTranslatableException(Throwable t) {
+        if (isAssignable(t.getClass()))
+            return t;
+        Throwable nested = t.getCause();
+        if (nested != null && nested != t) {
+            return searchForKnownButNonTranslatableException(nested);
+        }
+        return null;
+    }
+    
+    private boolean isAssignable(Class<?> t) {
+        if (exceptionTypes.contains(t.getName())) {
+            return true;
+        }
+        if (t.getSuperclass() != Object.class) {
+            return isAssignable(t.getSuperclass());
+        }
+        return false;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/ExceptionAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/TradingServiceAdapterImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/TradingServiceAdapterImpl.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/TradingServiceAdapterImpl.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/TradingServiceAdapterImpl.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.server;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+
+import org.apache.openjpa.trader.client.TradingServiceAdapter;
+import org.apache.openjpa.trader.domain.Ask;
+import org.apache.openjpa.trader.domain.Bid;
+import org.apache.openjpa.trader.domain.LogStatement;
+import org.apache.openjpa.trader.domain.Match;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+import org.apache.openjpa.trader.domain.Trade;
+import org.apache.openjpa.trader.domain.Trader;
+import org.apache.openjpa.trader.service.Exchange;
+import org.apache.openjpa.trader.service.MockTradingService;
+import org.apache.openjpa.trader.service.TradingService;
+
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+
+/**
+ * The server side implementation of the RPC service.
+ */
+@SuppressWarnings("serial")
+public class TradingServiceAdapterImpl extends RemoteServiceServlet implements TradingServiceAdapter {
+    
+    TradingService _del;
+    
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        String unit = config.getInitParameter("persistence.unit");
+        String mock = config.getInitParameter("mock");
+        _del = ("true".equalsIgnoreCase(mock)) ? new MockTradingService() : new Exchange(unit);
+    }
+    
+    public void destroy() {
+        _del.close();
+        super.destroy();
+    }
+    
+    public Ask ask(Trader trader, Stock stock, int volume, double price) {
+        try {
+            return _del.ask(trader, stock, volume, price);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public Bid bid(Trader trader, Stock stock, int volume, double price) {
+        try {
+            return _del.bid(trader, stock, volume, price);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public Tradable withdraw(Tradable t) {
+        try {
+            return _del.withdraw(t);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public Tradable refresh(Tradable t) {
+        try {
+            return _del.refresh(t);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public Stock getStock(String symbol) {
+        try {
+            return _del.getStock(symbol);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public List<Stock> getStocks() {
+        try {
+            return new ArrayList<Stock>(_del.getStocks());
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public List<Trade> getTrades(Timestamp from, Timestamp to) {
+        try {
+            return _del.getTrades(from, to);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public List<Trade> getTrades(Trader trader, Boolean boughtOrsold, Timestamp from, Timestamp to) {
+        try {
+            return _del.getTrades(trader, boughtOrsold, from, to);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public Trader login(String trader) throws RuntimeException {
+        try {
+            return _del.login(trader);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public List<Match> matchAsk(Ask ask) {
+        try {
+            return new ArrayList<Match>(_del.matchAsk(ask));
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public List<Match> matchBid(Bid bid) {
+        try {
+            return new ArrayList<Match>(_del.matchBid(bid));
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    public Trade trade(Match match) {
+        try {
+            return _del.trade(match);
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+    
+    @Override
+    public List<LogStatement> getLog() {
+        try {
+            return _del.getLog();
+        } catch (Throwable e) {
+            throw translate(e);
+        }
+    }
+
+    RuntimeException translate(Throwable t) {
+        t.printStackTrace();
+        return new ExceptionAdapter().translate(t);
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/server/TradingServiceAdapterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/BufferedLog.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/BufferedLog.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/BufferedLog.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/BufferedLog.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.log.LogFactory;
+import org.apache.openjpa.trader.domain.LogStatement;
+
+/**
+ * Specialized log to consolidate multiple logs into a single one.
+ * Selects only query related messages.
+ * <br>
+ * Designed to capture multiple logs used by different slices. It would have 
+ * been more useful to capture the slice thread that executed the query, but
+ * that is not possible in all cases as the log statement is emitted from the
+ * kernel's main thread.
+ *      
+ * @author Pinaki Poddar
+ *
+ */
+public class BufferedLog implements LogFactory, Configurable  {
+    private int _history    = 100;
+    private String _diagCtx;
+    private Configuration _conf;
+    static String[] SQL_MARKERS  = {"INSERT INTO", "SELECT", "UPDATE", "DELETE"};
+    static String[] JPQL_MARKERS = {"Executing query: ["};
+    static List<String> CHANNELS = Arrays.asList(OpenJPAConfiguration.LOG_QUERY, JDBCConfiguration.LOG_SQL);
+    
+    private static LinkedList<LogStatement> _messageModel;
+    static {
+        _messageModel = new LinkedList<LogStatement>();
+    }
+    
+    public void setConfiguration(Configuration conf) {
+        _conf = conf;
+    }
+
+    public void endConfiguration() {
+    }
+
+    public void startConfiguration() {
+    }
+
+    
+    public BufferedLog() {
+        super();
+    }
+    
+    public void setDiagnosticContext(String ctx) {
+        System.err.println(ctx);
+        _diagCtx = ctx;
+    }
+    
+    
+    public Log getLog(String channel) {
+        return new ChannelLog(channel);
+    }
+
+    public void setHistory(int i) {
+        _history = Math.max(i, 1);
+    }
+    
+    public int getHistory() {
+        return _history;
+    }
+    
+    String getContext() {
+        if (_diagCtx != null)
+            return _diagCtx;
+        if (_conf == null || isEmpty(_conf.getId()))
+            return "";
+        else {
+            _diagCtx = _conf.getId();
+            return _conf.getId();
+        }
+    }
+    
+    void addStatement(LogStatement stmt) {
+        _messageModel.addLast(stmt);
+        if (_messageModel.size() > _history) {
+            _messageModel.removeFirst();
+        }
+    }
+    
+    boolean isEmpty(String s) {
+        return s == null || s.trim().length() == 0;
+    }
+    
+    public List<LogStatement> get() {
+        List<LogStatement> result = new ArrayList<LogStatement>(_messageModel);
+        _messageModel.clear();
+        return result;
+    }
+
+    
+    public class ChannelLog implements Log {
+        final String _channel;
+        final String _thread;
+        public ChannelLog(String channel) {
+            _channel = channel;
+            _thread = Thread.currentThread().getName();
+        }
+        
+        public void error(Object o) {
+            createLogStatement("ERROR", o, null);
+        }
+
+        public void error(Object o, Throwable t) {
+            createLogStatement("ERROR", o, t);
+        }
+
+        
+        public void fatal(Object o) {
+            createLogStatement("FATAL", o, null);
+        }
+
+        
+        public void fatal(Object o, Throwable t) {
+            createLogStatement("FATAL", o, t);
+        }
+
+        
+        public void info(Object o) {
+            createLogStatement("INFO", o, null);
+        }
+
+        
+        public void info(Object o, Throwable t) {
+            createLogStatement("INFO", o, t);
+        }
+
+        
+        public boolean isErrorEnabled() {
+            return true;
+        }
+        
+        public boolean isFatalEnabled() {
+            return true;
+        }
+        
+        public boolean isInfoEnabled() {
+            return CHANNELS.contains(_channel);
+        }
+        
+        public boolean isTraceEnabled() {
+            return CHANNELS.contains(_channel);
+        }
+        
+        public boolean isWarnEnabled() {
+            return true;
+        }
+
+        
+        public void trace(Object o) {
+            createLogStatement("TRACE", o, null);
+        }
+        
+        public void trace(Object o, Throwable t) {
+            createLogStatement("TRACE", o, t);
+        }
+        
+        public void warn(Object o) {
+            createLogStatement("WARN", o, null);
+        }
+        
+        public void warn(Object o, Throwable t) {
+            createLogStatement("WARN", o, t);
+        }
+        
+        protected void createLogStatement(String level, Object message, Throwable t) {
+            String msg = message == null ? null : message.toString();
+            msg = extractQuery(msg);
+            if (msg == null) {
+                return;
+            }
+            addStatement(new LogStatement(level, getContext(), 
+                    _thread, _channel, msg));
+            if (t != null) {
+                StringWriter buffer = new StringWriter();
+                t.printStackTrace(new PrintWriter(buffer));
+                addStatement(new LogStatement(
+                        level, getContext(), 
+                        Thread.currentThread().getName(), _channel, 
+                        buffer.toString()));
+            }
+        }
+        
+        public String extractQuery(String msg) {
+            if (msg == null)
+                return null;
+            if ("openjpa.jdbc.SQL".equals(_channel)) {
+                return getQuery(msg, SQL_MARKERS, true);
+            } else if ("openjpa.Query".equals(_channel)) {
+                return getQuery(msg, JPQL_MARKERS, false);
+            } 
+            return null;
+        }
+        
+        private String getQuery(String message, String[] markers, boolean sql) {
+            int k = -1;
+            for (int i = 0; i < markers.length; i++) {
+                k = message.indexOf(markers[i]);
+                if (k != -1) {
+                    int m = sql ? 0 : markers[i].length();
+                    return message.substring(k+m).trim();
+                }
+            }
+            return null;
+        }
+ 
+    }
+
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/BufferedLog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/Exchange.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/Exchange.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/Exchange.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/Exchange.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContextType;
+import javax.persistence.TypedQuery;
+
+import org.apache.openjpa.lib.log.LogFactory;
+import org.apache.openjpa.trader.domain.Ask;
+import org.apache.openjpa.trader.domain.Bid;
+import org.apache.openjpa.trader.domain.LogStatement;
+import org.apache.openjpa.trader.domain.Match;
+import org.apache.openjpa.trader.domain.Sector;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+import org.apache.openjpa.trader.domain.Trade;
+import org.apache.openjpa.trader.domain.Trader;
+
+@SuppressWarnings("serial")
+public class Exchange extends PersistenceService implements TradingService {
+    private BufferedLog log;
+    
+    public Exchange(String unit) {
+        this(unit, null);
+    }
+    
+    public Exchange(String unit, Map<String,Object> config) {
+        super(unit, false, PersistenceContextType.TRANSACTION, addLog(config));
+        LogFactory serverLog = getUnit().getConfiguration().getLogFactory();
+        try {
+            log = (BufferedLog)serverLog;
+        } catch (ClassCastException e) {
+            System.err.println("Local Log was loaded by " + BufferedLog.class.getClassLoader());
+            System.err.println("Server Log was loaded by " + serverLog.getClass().getClassLoader());
+            e.printStackTrace();
+        }
+        populate();
+        new MarketFeed(this).start(60*1000);
+    }
+    
+    
+    public Ask ask(Trader trader, Stock stock, int volume, double price) {
+        EntityManager em = getEntityManager();
+        begin();
+        Ask ask = new Ask(trader, stock, price, volume);
+        em.persist(ask);
+        commit();
+        return ask;
+    }
+
+    
+    public Bid bid(Trader trader, Stock stock, int volume, double price) {
+        EntityManager em = getEntityManager();
+        begin();
+        Bid bid = new Bid(trader, stock, price, volume);
+        em.persist(bid);
+        commit();
+        return bid;
+    }
+
+    
+    public List<Match> matchBid(Bid bid) {
+        EntityManager em = getEntityManager();
+        begin();
+        TypedQuery<Match> q = em.createQuery(MATCH_BID, Match.class)
+                                .setParameter("bid", bid);
+        List<Match> matches = q.getResultList();
+        commit();
+        return matches;
+    }
+    
+    public List<Match> matchAsk(Ask ask) {
+        EntityManager em = getEntityManager();
+        begin();
+        TypedQuery<Match> q = em.createQuery(MATCH_ASK, Match.class)
+                                .setParameter("ask", ask);
+        List<Match> matches = q.getResultList();
+        commit();
+        return matches;
+    }
+    
+    @Override
+    public Tradable withdraw(Tradable t) {
+        if (t.isTraded()) {
+            throw new IllegalStateException("Can not widthdraw " + t + ". It has already been traded");
+        }
+        EntityManager em = getEntityManager();
+        begin();
+        em.createQuery("delete from " + (t instanceof Ask ? "Ask" : "Bid") + " t where t.id=:id")
+          .setParameter("id", t.getId())
+          .executeUpdate();
+        commit();
+        return t;
+    }
+    
+    /**
+     * Refresh may fail for various reasons.
+     * The tradable might have been traded or withdrawn.
+     */
+    @Override
+    public Tradable refresh(Tradable t) {
+        EntityManager em = getEntityManager();
+        begin();
+        t = em.find(t.getClass(), t.getId());
+        commit();
+        return t;
+    }
+    
+    public Trade trade(Match match) {
+        EntityManager em = getEntityManager();
+        begin();
+        Ask ask = em.merge(match.getAsk());
+        Bid bid = em.merge(match.getBid());
+        Trade trade = new Trade(ask, bid);
+        em.persist(trade);
+        commit();
+        return trade;
+    }
+
+    public Trader login(String traderName) {
+        EntityManager em = getEntityManager();
+        begin();
+        Trader trader = em.find(Trader.class, traderName);
+        if (trader == null) {
+            trader = new Trader(traderName);
+            em.persist(trader);
+        }
+        commit();
+        return trader;
+    }
+
+    public Stock getStock(String symbol) {
+        EntityManager em = getEntityManager();
+        begin();
+        Stock stock = em.find(Stock.class, symbol);
+        em.refresh(stock);
+        commit();
+        return stock;
+    }
+
+    public List<Trade> getTrades(Timestamp from, Timestamp to) {
+        EntityManager em = getEntityManager();
+        begin();
+        List<Trade> result = em.createQuery(QUERY_TRADE_BY_PERIOD, Trade.class)
+          .setParameter("from", from.getNanos())
+          .setParameter("to", to.getNanos())
+          .getResultList();
+        commit();
+        return result;
+    }
+
+    public List<Trade> getTrades(Trader trader, Boolean bought, Timestamp from, Timestamp to) {
+        EntityManager em = getEntityManager();
+        begin();
+        StringBuilder jpql = new StringBuilder(QUERY_TRADE_BY_PERIOD);
+        if (Boolean.TRUE.equals(bought)) {
+            jpql.append(" AND t.buyer = : buyer");
+        } else if (Boolean.FALSE.equals(bought)) {
+            jpql.append(" AND t.seller = : seller");
+        }
+        TypedQuery<Trade> q = em.createQuery(jpql.toString(), Trade.class);
+        if (Boolean.TRUE.equals(bought)) {
+            q.setParameter("buyer", trader);
+        } else if (Boolean.FALSE.equals(bought)) {
+            q.setParameter("seller", trader);
+        }
+        q.setParameter("from", from.getNanos())
+         .setParameter("to", to.getNanos());
+        
+        List<Trade> result = q.getResultList();
+        commit();
+        return result;
+    }
+
+    
+    public void populate() {
+        Object[][] data = {
+                new Object[]{"IBM",  Sector.INFRASTRUCTURE, 140.03},
+                new Object[]{"ORCL", Sector.INFRASTRUCTURE, 20.04},
+                new Object[]{"MSFT", Sector.INFRASTRUCTURE, 32.0},
+                new Object[]{"Bayer", Sector.HEALTHCARE, 120.45},
+                new Object[]{"SMNS", Sector.HEALTHCARE, 34.98},
+                new Object[]{"CSCO", Sector.INFRASTRUCTURE, 23.45},
+                new Object[]{"GS",   Sector.FINACE, 120.09},
+                new Object[]{"IFN", Sector.FINACE, 265.87},
+               
+        };
+        EntityManager em = getEntityManager();
+        
+        begin();
+        List<Stock> stocks = em.createQuery(GET_ALL_STOCKS, Stock.class).getResultList();
+        if (stocks.isEmpty()) {
+            for (int i = 0; i < data.length; i++) {
+                Object[] d = data[i];
+                Stock stock = new Stock((String)d[0], (String)d[0], (Sector)d[1], (Double)d[2]);
+                em.persist(stock);
+            }
+        
+            for (int i = 0; i < 4; i++) {
+                Trader trader = new Trader("Trader-"+i);
+                em.persist(trader);
+            }
+            stocks = em.createQuery(GET_ALL_STOCKS, Stock.class).getResultList();
+        }
+        commit();
+    }
+
+
+    
+    public List<Stock> getStocks() {
+        EntityManager em = getEntityManager();
+        begin();
+        List<Stock> stocks = em.createQuery(GET_ALL_STOCKS, Stock.class).getResultList();
+        commit();
+        return stocks;
+    }
+    
+
+    public List<LogStatement> getLog() {
+        if (log == null) {
+            return new ArrayList<LogStatement>();
+        }
+        return log.get();
+    }
+
+    @Override
+    public void close() {
+        super.close();
+    }
+    
+    static Map<String,Object> addLog(Map<String,Object> config) {
+        if (config == null) {
+            config = new HashMap<String, Object>();
+        }
+        config.put("openjpa.Log", BufferedLog.class.getName());
+        return config;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/Exchange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MarketFeed.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MarketFeed.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MarketFeed.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MarketFeed.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+import java.util.List;
+import java.util.Random;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.trader.domain.Stock;
+
+public class MarketFeed extends TimerTask {
+    /**
+     * A query to find symbols of all stocks.
+     */
+    String GET_ALL_STOCKS = "select s from Stock s";
+    private static final Random rng = new Random(System.currentTimeMillis());
+    private static final int MAX_CHANGE = 10;
+    private final PersistenceService _service;
+
+    MarketFeed(PersistenceService service) {
+        super();
+        _service = service;
+    }
+
+    void start(long period) {
+        new Timer(true).schedule(this, 0, period);
+    }
+
+    @Override
+    public void run() {
+        EntityManager em = _service.newEntityManager();
+        em.getTransaction().begin();
+        List<Stock> stocks = em.createQuery(GET_ALL_STOCKS, Stock.class).getResultList();
+        int n = stocks.size();
+        for (int i = 0; i < n; i++) {
+            if (rng.nextDouble() < 0.25) {
+                Stock stock = stocks.get(i);
+                double oldPrice = stock.getMarketPrice();
+                double delta = (rng.nextDouble() - 0.5) * MAX_CHANGE;
+                double newPrice = Math.max(oldPrice + delta, 0.01);
+                stock.setMarketPrice(newPrice);
+            }
+        }
+        em.getTransaction().commit();
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MarketFeed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MockTradingService.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MockTradingService.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MockTradingService.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MockTradingService.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.openjpa.trader.domain.Ask;
+import org.apache.openjpa.trader.domain.Bid;
+import org.apache.openjpa.trader.domain.LogStatement;
+import org.apache.openjpa.trader.domain.Match;
+import org.apache.openjpa.trader.domain.Sector;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+import org.apache.openjpa.trader.domain.Trade;
+import org.apache.openjpa.trader.domain.Trader;
+
+
+public class MockTradingService implements TradingService {
+    List<Ask> _asks = new ArrayList<Ask>();
+    List<Bid> _bids = new ArrayList<Bid>();
+    List<Trade> _trades = new ArrayList<Trade>();
+    List<Stock> _stocks = new ArrayList<Stock>();
+    List<Trader> _traders = new ArrayList<Trader>();
+    List<LogStatement> _logs = new ArrayList<LogStatement>();
+    int counter = 0;
+    private static Random rng = new Random(System.currentTimeMillis());
+    
+    public MockTradingService() {
+        Sector[] sectors = Sector.values();
+        for (int i = 0; i < 10; i++) {
+            Stock stock = new Stock("Stock-"+i, "Company-"+i, sectors[rng.nextInt(sectors.length)],
+                    10*rng.nextDouble());
+            _stocks.add(stock);
+        }
+    }
+    
+    @Override
+    public Ask ask(Trader trader, Stock stock, int volume, double price) {
+        Ask ask = new Ask(trader, stock, price, volume);
+        _asks.add(ask);
+        log("Added " + ask + " " + counter++);
+        return ask;
+    }
+
+    @Override
+    public Bid bid(Trader trader, Stock stock, int volume, double price) {
+        Bid bid = new Bid(trader, stock, price, volume);
+        _bids.add(bid);
+        log("Added new " + bid + " " + counter++);
+        return bid;
+    }
+
+    @Override
+    public List<LogStatement> getLog() {
+        int from = Math.max(_logs.size()-5, 0);
+        List<LogStatement> result = new ArrayList<LogStatement>();
+        for (int i = from; i < _logs.size(); i++)
+            result.add(_logs.get(i));
+        return result;
+    }
+
+    @Override
+    public Stock getStock(String symbol) {
+        for (Stock s : _stocks) {
+            if (s.getSymbol().equals(symbol))
+                return s;
+        }
+        log("No Stock " + symbol);
+        return null;
+    }
+
+    @Override
+    public List<Stock> getStocks() {
+        for (Stock s : _stocks) {
+            double delta = 10*(2*rng.nextDouble()-1)/100;
+            s.setMarketPrice(s.getMarketPrice() + s.getMarketPrice()*delta);
+        }
+        return _stocks;
+    }
+
+    @Override
+    public List<Trade> getTrades(Timestamp from, Timestamp to) {
+        return null;
+    }
+
+    @Override
+    public List<Trade> getTrades(Trader trader, Boolean boughtOrsold, Timestamp from, Timestamp to) {
+        return null;
+    }
+
+    @Override
+    public Trader login(String trader) {
+        for (Trader t : _traders) {
+            if (t.getName().equals(trader))
+                return t;
+        } 
+        Trader t = new Trader(trader);
+        _traders.add(t);
+        return t;
+    }
+
+    @Override
+    public List<Match> matchAsk(Ask ask) {
+        List<Match> result = new ArrayList<Match>();
+        for (Bid bid : _bids) {
+            if (matches(ask, bid)) {
+                result.add(new Match(ask, bid));
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public List<Match> matchBid(Bid bid) {
+        List<Match> result = new ArrayList<Match>();
+        for (Ask ask : _asks) {
+            if (matches(ask, bid)) {
+                result.add(new Match(ask, bid));
+            }
+        }
+        return result;
+    }
+    
+    public Tradable refresh(Tradable t) {
+        return t;
+    }
+
+    @Override
+    public Trade trade(Match match) {
+        Trade trade = new Trade(match.getAsk(), match.getBid());
+        return trade;
+    }
+    
+    private boolean matches(Ask ask, Bid bid) {
+        return ((bid.getStock().getSymbol().equals(ask.getStock().getSymbol()))
+                &&  (!bid.getBuyer().equals(ask.getSeller()))
+                &&  (bid.getPrice() >= ask.getPrice())
+                &&  (bid.getVolume()) <= ask.getVolume());
+    }
+    
+    private void log(String s) {
+        _logs.add(new LogStatement("INFO", "Context", "Thread", "Channel", s));
+        System.err.println("server log:" + s );
+    }
+
+    @Override
+    public Tradable withdraw(Tradable t) {
+//        t.expire();
+        return t;
+    }
+
+    @Override
+    public void close() {
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/MockTradingService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/PersistenceService.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/PersistenceService.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/PersistenceService.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/PersistenceService.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Observable;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.PersistenceContextType;
+
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+
+/**
+ * An abstract utility for JPA based service. 
+ * This thin wrapper over a {@link EntityManagerFactory Persistence Unit} maintains
+ * <LI>per-thread persistence context
+ * <LI>relinquishes direct transaction control under a managed environment 
+ * 
+ * @see #getEntityManager()
+ * @see #newEntityManager()
+ * 
+ * @author Pinaki Poddar
+ * 
+ */
+@SuppressWarnings("serial")
+public abstract class PersistenceService extends Observable implements Serializable {
+    private final OpenJPAEntityManagerFactory emf;
+    private final String unitName;
+    private final boolean isManaged;
+    private final PersistenceContextType scope;
+    
+    private ThreadLocal<EntityManager> thread = new ThreadLocal<EntityManager>();
+    private ReentrantLock lock = new ReentrantLock();
+
+    protected PersistenceService(String unit) {
+        this(unit, false, PersistenceContextType.EXTENDED, null);
+    }
+    
+    protected PersistenceService(String unit, boolean managed, PersistenceContextType scope,
+            Map<String,Object> config) {
+        this.emf = OpenJPAPersistence.cast(Persistence.createEntityManagerFactory(unit, config));
+        this.unitName  = unit;
+        this.isManaged = managed;
+        this.scope     = scope;
+    }
+    
+    public final OpenJPAEntityManagerFactory getUnit() {
+        return emf;
+    }
+
+    public final String getUnitName() {
+        return unitName;
+    }
+    
+    public final boolean isManaged() {
+        return isManaged;
+    }
+    
+    public final PersistenceContextType getContextType() {
+        return scope;
+    }
+
+    /**
+     * Gets an entity manager associated with the current thread. If the
+     * current thread is not associated with any entity manager or the
+     * associated entity manager has been closed, creates a new entity manager
+     * and associates with the current thread.
+     * 
+     * @return an entity manager associated with the current thread.
+     */
+    protected EntityManager getEntityManager() {
+        try {
+            lock.lock();
+            EntityManager em = thread.get();
+            if (em == null || !em.isOpen()) {
+                em = emf.createEntityManager();
+                thread.set(em);
+            }
+            return em;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Creates a new entity manager. The entity manager is not associated with
+     * the current thread.
+     */
+    protected EntityManager newEntityManager() {
+        return emf.createEntityManager();
+    }
+
+    /**
+     * Begins a transaction on the current thread. If the thread is associated
+     * with a persistence context, then a transaction is started if necessary.
+     * If the thread is not associated with a persistence context, then a new
+     * context is created, associated with the thread, new transaction is
+     * started.
+     * 
+     * @see #getEntityManager()
+     */
+    protected EntityManager begin() {
+        try {
+            lock.lock();
+            EntityManager em = getEntityManager();
+            if (isManaged) {
+                em.joinTransaction();
+            } else {
+                if (!em.getTransaction().isActive()) {
+                    em.getTransaction().begin();
+                }
+            }
+            return em;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Commits a transaction on the current thread.
+     */
+    protected void commit() {
+        try {
+            lock.lock();
+            EntityManager em = getEntityManager();
+            if (isManaged) {
+                em.flush();
+            } else {
+                assertActive();
+                em.getTransaction().commit();
+            }
+            if (scope == PersistenceContextType.TRANSACTION) {
+                em.clear();
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Rolls back a transaction on the current thread.
+     */
+    protected void rollback() {
+        try {
+            lock.lock();
+            EntityManager em = getEntityManager();
+            if (isManaged) {
+                
+            } else {
+                em.getTransaction().rollback();
+            }
+            if (scope == PersistenceContextType.TRANSACTION) {
+                em.clear();
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+    
+    public void close() {
+        try {
+            EntityManager em = thread.get();
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+                em.close();
+            }
+            thread.set(null);
+            emf.close();
+        } finally {
+            
+        }
+        
+    }
+
+    /**
+     * Assert current thread is associated with an active transaction.
+     */
+    protected void assertActive() {
+        EntityManager em = thread.get();
+        String thread = Thread.currentThread().getName();
+        assertTrue("No persistent context is associated with " + thread, em != null);
+        assertTrue("Persistent context " + em + " associated with " + thread + " has been closed", em.isOpen());
+        if (!isManaged) {
+            assertTrue("Persistent context " + em + " associated with " + thread + " has no active transaction", 
+                    em.getTransaction().isActive());
+        }
+    }
+
+    protected void assertTrue(String s, boolean p) {
+        if (!p) {
+            System.err.println(s);
+            throw new RuntimeException(s);
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/PersistenceService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradeEvent.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradeEvent.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradeEvent.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradeEvent.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+public class TradeEvent {
+    enum Type {LOGIN, ASK, BID, WITHDRAW, REFRESH, TRADE, MATCH, 
+               STOCK_LOOKUP, QUERY_TRADE, MARKET_FEED};
+    
+    public final Type type;
+    public final long time;
+    public final String description;
+    
+    public TradeEvent(Type type, long elapsedTime) {
+        this(type, elapsedTime, "");
+    }
+    
+    public TradeEvent(Type type, long elapsedTime, String txt) {
+        this.type = type;
+        this.time = elapsedTime;
+        this.description = txt;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradeEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradingService.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradingService.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradingService.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradingService.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+import org.apache.openjpa.trader.domain.Ask;
+import org.apache.openjpa.trader.domain.Bid;
+import org.apache.openjpa.trader.domain.LogStatement;
+import org.apache.openjpa.trader.domain.Match;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+import org.apache.openjpa.trader.domain.Trade;
+import org.apache.openjpa.trader.domain.Trader;
+
+/**
+ * A service to place offer to {@link Bid buy} and {@link Ask sell} stocks, 
+ * matches asks to bids and registers trades.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public interface TradingService {
+    /**
+     * A query to find symbols of all stocks.
+     */
+    String GET_ALL_STOCKS = "select s from Stock s";
+    
+    /**
+     * A query to match asks to a given bid.
+     */
+    String MATCH_BID  = "select new Match(a,b) from Ask a, Bid b " 
+                      + "where b = :bid and a.stock.symbol = b.stock.symbol " 
+                      + "and a.price <= b.price and a.volume >= b.volume " 
+                      + "and NOT(a.seller = b.buyer) and a.trade is NULL and b.trade is NULL";
+//                      + "order by a.price ASC";
+    
+    /**
+     * A query to match bids of a given ask.
+     */
+    String MATCH_ASK  = "select new Match(a,b) from Ask a, Bid b " 
+                      + "where a = :ask  and a.stock.symbol = b.stock.symbol " 
+                      + "and a.price <= b.price and a.volume >= b.volume " 
+                      + "and NOT(a.seller = b.buyer) and a.trade is NULL and b.trade is NULL"; 
+//                      + "order by b.price DESC";
+    
+    /**
+     * A query to find a trader by his/her name.
+     */
+    String QUERY_TRADER_BY_NAME = "select t from Trader t where t.name=:name";
+    
+    
+    /**
+     * A query to find all trades in a given period.
+     */
+    String QUERY_TRADE_BY_PERIOD = "select t from Trade t where t.id between (:from, :to)";
+    
+    
+    public static final String DEFAULT_UNIT_NAME = "exchange";
+    
+    /**
+     * Gets the list of stocks registered with this service.
+     */
+    List<Stock> getStocks();
+    
+    /**
+     * Logs in a trader of given name.
+     * 
+     * @param trader
+     * @return
+     */
+    Trader login(String trader);
+    
+    /**
+     * The given Trader asks (offers to sell) the given stock at given price. 
+     * @param trader
+     * @param stock
+     * @param volume
+     * @param price
+     * @return
+     */
+    Ask ask(Trader trader, Stock stock, int volume, double price);
+    
+    
+    /**
+     * The given Trader bids (offers to buy) the given stock at given price. 
+     * @param trader
+     * @param stock
+     * @param volume
+     * @param price
+     * @return
+     */
+    Bid bid(Trader trader, Stock stock, int volume, double price);
+    
+    /**
+     * Matches existing asks to the given bid.
+     * @param bid the bid to be matched
+     * @return possible (uncommitted) trades matching the bids
+     */
+    List<Match> matchBid(Bid bid);
+    
+    /**
+     * Matches existing bids to the given ask.
+     * @param ask the ask to be matched with the bids
+     * @return possible (uncommitted) trades matching the given ask
+     */
+    List<Match> matchAsk(Ask ask);
+    
+    Tradable withdraw(Tradable t);
+    Tradable refresh(Tradable t);
+    
+    void close();
+    /**
+     * Registers the given trade.
+     * @param trade
+     */
+    Trade trade(Match match);
+    
+    /**
+     * Gets the trades executed between the given time periods.
+     * @param from
+     * @param to
+     * @return
+     */
+    List<Trade> getTrades(Timestamp from, Timestamp to);
+    
+    /**
+     * Gets the trades executed by the given trader between the given time periods.
+     * @param from
+     * @param to
+     * @return
+     */
+    List<Trade> getTrades(Trader trader, Boolean boughtOrsold, Timestamp from, Timestamp to);
+    
+    /**
+     * Gets the current value of the stock given its symbol.
+     * @param symbol
+     * @return
+     */
+    Stock getStock(String symbol);
+    
+    /**
+     * Gets the statements logged since the last call.
+     * @return
+     */
+    List<LogStatement> getLog();
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/TradingService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/slice/SectorDistributionPolicy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/slice/SectorDistributionPolicy.java?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/slice/SectorDistributionPolicy.java (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/slice/SectorDistributionPolicy.java Tue Aug 24 18:11:25 2010
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.openjpa.trader.service.slice;
+
+import java.util.List;
+
+import org.apache.openjpa.slice.DistributionPolicy;
+import org.apache.openjpa.trader.domain.Stock;
+import org.apache.openjpa.trader.domain.Tradable;
+import org.apache.openjpa.trader.domain.Trader;
+
+/**
+ * Distributes each persistent domain instances of OpenTrader model into specific slice
+ * based on the sector.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class SectorDistributionPolicy implements DistributionPolicy {
+    /**
+     * This distribution policy determines the sector of the stock and
+     * picks the slice of the given list of slices at ordinal index of the
+     * enumerated Sector.
+     */
+    public String distribute(Object pc, List<String> slices, Object context) {
+        Stock stock = null;
+        if (pc instanceof Tradable) {
+            stock = ((Tradable)pc).getStock();
+        } else if (pc instanceof Stock) {
+            stock = (Stock)pc;
+        } else if (pc instanceof Trader) {
+            throw new IllegalArgumentException("Trader should have been replicated");
+        }
+//        if (stock == null) {
+//            throw new IllegalStateException(pc + "(" + pc.getClass() + ") is not associated with a Stock");
+//        }
+        return stock != null ? slices.get(stock.getSector().ordinal()) : null;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/java/org/apache/openjpa/trader/service/slice/SectorDistributionPolicy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/opentrader/src/main/resources/css/OpenTrader.css
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/opentrader/src/main/resources/css/OpenTrader.css?rev=988644&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/opentrader/src/main/resources/css/OpenTrader.css (added)
+++ openjpa/trunk/openjpa-examples/opentrader/src/main/resources/css/OpenTrader.css Tue Aug 24 18:11:25 2010
@@ -0,0 +1,337 @@
+/**
+ * The stylesheet for OpenTrader sample application.
+ * 
+**/
+
+/**
+ *  GWT Widgets have pre-defined style names. These pre-defined style names
+ *  can be redecorated for a specific application.
+ *
+**/
+.gwt-Label {
+   font-family: "Palatino Linotype";
+}
+
+.gwt-PopupPanel {
+   font-family: "Palatino Linotype";
+   border: 10px;
+}
+
+.gwt-PopupPanel .popupContent {
+   font-family: "Palatino Linotype";
+   border: 50px;
+}
+
+/**
+ * LoginDialog is a specialized PopupPanel that organizes its content in a FlexTable.
+ * The CSS styles apply to the table cells.
+**/
+.login {
+   color:white;
+   font-weight:bold;
+   border: 10px;
+   background-color:#005B9A;
+   cell-spacing:10px;
+   cell-padding:10px;
+}
+
+/**
+ * A special style apply to the caption of the login dialog -- which is the first row
+ * of the FlexTable that the LoginDialog wraps in a PopupPanel.
+**/
+.login-caption {
+   font-family: "Palatino Linotype";
+   font-size:20pt;
+   font-weight:bold;
+   color: white;
+}
+
+/** ---------------------------------------------------------------------------
+ *                  CSS Styles used in ScrollableTable.
+ *  ---------------------------------------------------------------------------
+**/
+
+.cbg-RP { 
+   background-color:#005B9A;
+   border-color: #005B9A;
+}
+
+.table-caption {
+  background-color:#005B9A;
+  font-size:1.1em;
+  font-weight:bold;
+  color:#FFFFFF;
+  font-family: "Palatino Linotype";
+}
+
+.column-header {
+  background-color:#74C2E1;
+  font-weight:bold;
+  font-family: "Palatino Linotype";
+  color:#838984;
+}
+.row-even {
+  background-color:#FFFFFF;
+}
+.row-odd {
+  background-color:#CCCCCC;
+}
+
+.progressMonitor-caption {
+  background-color:#005B9A;
+   font-family: "Palatino Linotype";
+   font-size:14pt;
+   font-weight:bold;
+   color: white;
+}
+
+.openjpa-MessageBox {
+   align:center;
+   background-color:#EEEEEE;
+   width:300px;
+   height:150px;
+}
+
+
+
+.header {
+  font-size: 20pt;
+  font-weight: bold;
+  color: #005B9A;
+   font-family: "Palatino Linotype";
+}
+.hello {
+  float:right;
+  text-align:right;
+  margin-right:1em;
+  
+}
+.error-message {
+   color:red;
+   font-weight:plain;
+   word-wrap:word-spacing;
+}
+
+.table-header {
+	color:blue;
+	background-color:green;
+   font-family: "Palatino Linotype";
+}
+
+
+#LogoPanel {
+  position: absolute;
+  top:0px;
+  left:10px;
+  width: 800px;
+  height: 40px;
+  border-style:double;
+  font-size: 20pt;
+  font-weight: bold;
+  color: #0000FF;
+/*  vertical-align:-25%; */
+}
+/** Panel on top-right corner displays current Trader details **/ 
+#TraderPanel {
+  position: absolute;
+  top:10px;
+  right:10px;
+  width: 300px;
+  height: 30px;
+  border-style:double;
+}
+/** Stock Panel displays the current stock prices that are being regularly refreshed **/
+#StockPanel {
+  position: absolute;
+  top:60px;
+  left:100px;
+  width: 400px;
+  height:800px;
+  border-style:double;
+}
+
+/** Ask Panel controls placing an offer to sell a stock **/
+#AskPanel {
+  position: absolute;
+  top:60px;
+  left:500px;
+  width: 400px;
+  height: 200px;
+  border-style:double;
+}
+/** Bid Panel controls placing an offer to buy a stock **/
+#BidPanel {
+  position: absolute;
+  top:60px;
+  left:1000px;
+  width: 400px;
+  height:200px;
+  border-style:double;
+}
+/** Trade Panel controls commit to buy/sell a stock **/
+#TradePanel {
+  position: absolute;
+  top:300px;
+  left:500px;
+  width: 900px;
+  height:300px;
+  border-style:double;
+}
+
+#TradeHistoryPanel {
+  position: absolute;
+  top:60px;
+  left:1440px;
+  width: 460px;
+  height:540px;
+  border-style:double;
+}
+
+#ServerPanel {
+  position: absolute;
+  top:620px;
+  left:500px;
+  width: 1400px;
+  height:300px;
+  border-style:double;
+}
+#FooterPanel {
+  position: absolute;
+  top:1000px;
+  left:10px;
+  width: 1400px;
+  height:40px;
+  border-style:double;
+}
+
+/* stock list flex table */
+.StockTable {
+  border: 1px solid silver;
+  padding: 2px;
+  margin-bottom:6px;
+}
+
+/* stock list header row */
+.StockTableHeader {
+  background-color: #2062B8;
+  color: white;
+  font-weight: bold;
+  text-align:center;
+}
+
+.NumericColumn {
+  text-align: right;
+  width:8em;
+}
+
+.positive {
+  color: green;
+}
+
+.negative {
+  color: red;
+}
+
+.sql-select {
+  color:#005B9A;
+  font-family: "Courier New";
+  font-size:small;
+}
+.sql-insert {
+  color:#31B96E;
+  font-family: "Courier New";
+  font-size:small;
+  font-weight:bold;
+}
+.sql-update {
+  color:#C73B0B;
+  font-family: "Courier New";
+  font-size:small;
+}
+.sql-delete {
+  color:#FF0000;
+  font-family: "Courier New";
+  font-size:small;
+}
+
+
+
+
+
+h2 {
+  font-size: 2em;
+  font-weight: bold;
+  color: #777777;
+/**  margin: 40px 0px 70px; **/
+  text-align: left;
+  vertical-align:top;
+}
+
+.sendButton {
+  display: block;
+  font-size: 16pt;
+}
+
+/** Most GWT widgets already have a style name defined */
+.ErrorDialog {
+  top:400px;
+  left:400px;
+  width: 800px;
+}
+.gwt-DialogBox .Caption {
+  color:red;
+  font-weight:bold;
+  font-size:16pt;
+}
+
+.gwt-DialogBox .dialogContent {
+  margin : 2px;
+}
+
+.dialogVPanel {
+  width: 800px;
+  margin: 5px;
+}
+
+.serverResponseLabelError {
+  color: red;
+}
+
+/** Set ids using widget.getElement().setId("idOfElement") */
+#closeButton {
+  margin: 15px 6px 6px;
+}
+
+
+
+.TradeOrderWindow {
+  font-size:0.8em;
+  font-weight:bold;
+  color:#FFFFFF;
+  background-color:#0191C8;
+  width:40px;
+  height:25px;
+  margin: 4 10 4 10;
+}
+
+body, table td, select {
+  font-family: "Palatino Linotype";
+  font-size:small;
+}
+
+.gwt-Button {
+  margin: 0;
+  background-color:#74C2E1;
+  padding: 3px 5px;
+  text-decoration: none;
+   font-family: "Palatino Linotype";
+  font-size: small;
+  cursor: pointer;
+  cursor: hand;
+  background: url("images/hborder.png") repeat-x 0px -27px;
+  border: 1px outset #333;
+}
+.gwt-Anchor {
+   color:#FFFFFF;
+}
+

Propchange: openjpa/trunk/openjpa-examples/opentrader/src/main/resources/css/OpenTrader.css
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message