From e2884e9c2bba85eb7c041b0528d5af139fe66082 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 1 Nov 2013 23:41:15 +0000 Subject: [PATCH 1/7] [maven-release-plugin] copy for tag openjpa-parent-2.3.0 git-svn-id: https://svn.apache.org/repos/asf/openjpa/tags/openjpa-parent-2.3.0@1538090 13f79535-47bb-0310-9956-ffa450edef68 From 999338a19ec7bf3970218b143e38f1197f2c0111 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Thu, 21 Nov 2013 12:30:34 +0000 Subject: [PATCH 2/7] rename release tag to 2.3.0. no content changes git-svn-id: https://svn.apache.org/repos/asf/openjpa/tags/2.3.0@1544159 13f79535-47bb-0310-9956-ffa450edef68 From e664d67daa30a59cce88ca903925026d30aa7902 Mon Sep 17 00:00:00 2001 From: Mura Andrei Date: Wed, 30 Jul 2014 16:13:05 +0300 Subject: [PATCH 3/7] OPENJPA-2521 Cannot load entities from a different bundle in an OSGi environment. --- .../meta/AbstractCFMetaDataFactory.java | 22 ++- openjpa-lib/pom.xml | 7 +- .../lib/meta/OSGiBundleMetaDataIterator.java | 132 ++++++++++++++++++ 3 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java index 16e3027798..b92be215cc 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java @@ -45,18 +45,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; -import org.apache.openjpa.lib.meta.ClassArgParser; -import org.apache.openjpa.lib.meta.ClasspathMetaDataIterator; -import org.apache.openjpa.lib.meta.FileMetaDataIterator; -import org.apache.openjpa.lib.meta.JarFileURLMetaDataIterator; -import org.apache.openjpa.lib.meta.MetaDataFilter; -import org.apache.openjpa.lib.meta.MetaDataIterator; -import org.apache.openjpa.lib.meta.MetaDataParser; -import org.apache.openjpa.lib.meta.MetaDataSerializer; -import org.apache.openjpa.lib.meta.ResourceMetaDataIterator; -import org.apache.openjpa.lib.meta.URLMetaDataIterator; -import org.apache.openjpa.lib.meta.ZipFileMetaDataIterator; -import org.apache.openjpa.lib.meta.ZipStreamMetaDataIterator; +import org.apache.openjpa.lib.meta.*; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; @@ -759,6 +748,15 @@ public File run() { } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } + } else if ("bundle".equals(url.getProtocol())) { + + if (log.isTraceEnabled()) { + log.trace(_loc.get("scanning-osgi-bundle", url)); + } + + MetaDataIterator mdi = new OSGiBundleMetaDataIterator(url, newMetaDataFilter()); + scan(mdi, cparser, names, true, url); + } else { // Open an InputStream from the URL and sniff for a zip header. If it is, then this is // a URL with a jar-formated InputStream, as per the JPA specification. Otherwise, fall back diff --git a/openjpa-lib/pom.xml b/openjpa-lib/pom.xml index c828e61666..4aa90ad40f 100644 --- a/openjpa-lib/pom.xml +++ b/openjpa-lib/pom.xml @@ -78,7 +78,12 @@ org.apache.geronimo.specs geronimo-validation_1.0_spec provided - + + + org.osgi + org.osgi.core + 4.2.0 + diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java new file mode 100644 index 0000000000..559e32791e --- /dev/null +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java @@ -0,0 +1,132 @@ +/* + * 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.lib.meta; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +import java.io.*; +import java.net.URL; +import java.util.Enumeration; +import java.util.NoSuchElementException; + +/** + * Created by andrei on 24.07.2014. + */ +public class OSGiBundleMetaDataIterator implements MetaDataIterator, MetaDataFilter.Resource { + + private InputStream stream; + private Bundle bundle; + private Enumeration entries; + private MetaDataFilter filter; + private URL entry; + private URL last; + private byte[] buf; + + public OSGiBundleMetaDataIterator(URL bundleUrl, MetaDataFilter filter) { + + BundleContext ctx = FrameworkUtil.getBundle(OSGiBundleMetaDataIterator.class).getBundleContext(); + long bundleId = Long.parseLong(bundleUrl.getHost().substring(0, bundleUrl.getHost().indexOf("."))); + this.bundle = ctx.getBundle(bundleId); + entries = this.bundle.findEntries("/", "*.class", true); + this.filter = filter; + + } + + @Override + public boolean hasNext() throws IOException { + + if (entries == null) { + return false; + } + + if (entry != null) { + return true; + } + +// if (buf == null && last != null) +// _stream.closeEntry(); + last = null; + buf = null; + + if (!entries.hasMoreElements()) { + return false; + } + + URL tmp; + while ( entry == null && (entries.hasMoreElements() && (tmp = this.entries.nextElement()) != null)) { + entry = tmp; + stream = entry.openStream(); + if (filter != null && !this.filter.matches(this)) { + entry = null; + } + + } + + return entry != null; + + } + + @Override + public Object next() throws IOException { + + if (!hasNext()) { + throw new NoSuchElementException(); + } + + String name = entry.toString(); + last = entry; + entry = null; + + return name; + } + + @Override + public InputStream getInputStream() throws IOException { + if (last == null) + throw new IllegalStateException(); + + return last.openStream(); + } + + @Override + public File getFile() throws IOException { + return null; + } + + @Override + public void close() { + } + + @Override + public String getName() { + return entry.toString(); + } + + @Override + public byte[] getContent() throws IOException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + for (int r; (r = stream.read(buf)) != -1; bout.write(buf, 0, r)) ; + buf = bout.toByteArray(); + stream.close(); + return buf; + } +} From 1da2cdbaff96957dcc6cd4383a816e268e09d55b Mon Sep 17 00:00:00 2001 From: Mura Andrei Date: Thu, 31 Jul 2014 14:21:15 +0300 Subject: [PATCH 4/7] OPENJPA-2521 Cannot load entities from a different bundle in an OSGi environment. --- .../meta/AbstractCFMetaDataFactory.java | 306 +++++++++--------- openjpa-lib/pom.xml | 7 +- .../lib/meta/OSGiBundleMetaDataIterator.java | 130 ++++++++ 3 files changed, 288 insertions(+), 155 deletions(-) create mode 100644 openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java index 16e3027798..bb0a35c137 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java @@ -45,18 +45,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; -import org.apache.openjpa.lib.meta.ClassArgParser; -import org.apache.openjpa.lib.meta.ClasspathMetaDataIterator; -import org.apache.openjpa.lib.meta.FileMetaDataIterator; -import org.apache.openjpa.lib.meta.JarFileURLMetaDataIterator; -import org.apache.openjpa.lib.meta.MetaDataFilter; -import org.apache.openjpa.lib.meta.MetaDataIterator; -import org.apache.openjpa.lib.meta.MetaDataParser; -import org.apache.openjpa.lib.meta.MetaDataSerializer; -import org.apache.openjpa.lib.meta.ResourceMetaDataIterator; -import org.apache.openjpa.lib.meta.URLMetaDataIterator; -import org.apache.openjpa.lib.meta.ZipFileMetaDataIterator; -import org.apache.openjpa.lib.meta.ZipStreamMetaDataIterator; +import org.apache.openjpa.lib.meta.*; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; @@ -72,10 +61,10 @@ * @since 0.4.0 */ public abstract class AbstractCFMetaDataFactory - extends AbstractMetaDataFactory { + extends AbstractMetaDataFactory { private static final Localizer _loc = Localizer.forPackage - (AbstractMetaDataFactory.class); + (AbstractMetaDataFactory.class); protected Collection files = null; protected Collection urls = null; @@ -109,7 +98,7 @@ public void setFiles(String files) { for (int i = 0; i < strs.length; i++) { file = new File(strs[i]); if ((AccessController.doPrivileged( - J2DoPrivHelper.existsAction(file))).booleanValue()) + J2DoPrivHelper.existsAction(file))).booleanValue()) this.files.add(file); } } @@ -155,7 +144,7 @@ public void setResources(Collection rsrcs) { public void setResources(String rsrcs) { // keep list mutable so subclasses can add implicit locations this.rsrcs = (StringUtils.isEmpty(rsrcs)) ? null - : new ArrayList(Arrays.asList(Strings.split(rsrcs, ";", 0))); + : new ArrayList(Arrays.asList(Strings.split(rsrcs, ";", 0))); } /** @@ -173,11 +162,11 @@ public void setClasspathScan(Collection cpath) { public void setClasspathScan(String cpath) { // keep list mutable so subclasses can add implicit locations this.cpath = (StringUtils.isEmpty(cpath)) ? null - : new ArrayList(Arrays.asList(Strings.split(cpath, ";", 0))); + : new ArrayList(Arrays.asList(Strings.split(cpath, ";", 0))); } public boolean store(ClassMetaData[] metas, QueryMetaData[] queries, - SequenceMetaData[] seqs, int mode, Map output) { + SequenceMetaData[] seqs, int mode, Map output) { if (mode == MODE_NONE) return true; if (isMappingOnlyFactory() && (mode & MODE_MAPPING) == 0) @@ -187,9 +176,9 @@ public boolean store(ClassMetaData[] metas, QueryMetaData[] queries, mode |= MODE_MAPPING; Class cls = (metas.length == 0) ? null : metas[0].getDescribedType(); ClassLoader loader = repos.getConfiguration(). - getClassResolverInstance().getClassLoader(cls, null); - Map clsNames = new HashMap - ((int) (metas.length * 1.33 + 1)); + getClassResolverInstance().getClassLoader(cls, null); + Map clsNames = new HashMap + ((int) (metas.length * 1.33 + 1)); for (int i = 0; i < metas.length; i++) clsNames.put(metas[i].getDescribedType().getName(), metas[i]); @@ -199,7 +188,7 @@ public boolean store(ClassMetaData[] metas, QueryMetaData[] queries, Set queryFiles = null; if (isMappingOnlyFactory() || (mode & MODE_META) != 0) metaFiles = assignDefaultMetaDataFiles(metas, queries, seqs, mode, - clsNames); + clsNames); if (!isMappingOnlyFactory() && (mode & MODE_QUERY) != 0) queryFiles = assignDefaultQueryFiles(queries, clsNames); @@ -236,7 +225,7 @@ public boolean store(ClassMetaData[] metas, QueryMetaData[] queries, ser.addSequenceMetaData(seqs[i]); for (int i = 0; i < queries.length; i++) if (queries[i].getSourceMode() != MODE_QUERY - && (queries[i].getSourceMode() & mode) != 0) + && (queries[i].getSourceMode() & mode) != 0) ser.addQueryMetaData(queries[i]); int flags = ser.PRETTY; @@ -286,7 +275,7 @@ public boolean drop(Class[] cls, int mode, ClassLoader envLoader) { // parse metadata for all these classes if ((mode & (MODE_META | MODE_MAPPING)) != 0) { parser.setMode((isMappingOnlyFactory()) ? mode - : MODE_META | MODE_MAPPING | MODE_QUERY); + : MODE_META | MODE_MAPPING | MODE_QUERY); parse(parser, cls); } if (!isMappingOnlyFactory() && (mode & MODE_QUERY) != 0) { @@ -320,7 +309,7 @@ else if (!isMappingOnlyFactory()) // remove query mode metadatas so we can store them separately QueryMetaData[] queries = pr.getQueryMetaDatas(); List qqs = (!isMappingOnlyFactory() && (mode & MODE_QUERY) == 0) - ? null : new ArrayList(); + ? null : new ArrayList(); boolean rem; Class def; for (int i = 0; i < queries.length; i++) { @@ -328,9 +317,9 @@ else if (!isMappingOnlyFactory()) files.add(queries[i].getSourceFile()); def = queries[i].getDefiningType(); rem = (queries[i].getSourceMode() & mode) != 0 - && clsNames.contains((def == null) ? null : def.getName()); + && clsNames.contains((def == null) ? null : def.getName()); if (rem || (!isMappingOnlyFactory() - && queries[i].getSourceMode() == MODE_QUERY)) + && queries[i].getSourceMode() == MODE_QUERY)) pr.removeQueryMetaData(queries[i]); if (qqs != null && queries[i].getSourceMode() == MODE_QUERY && !rem) qqs.add(queries[i]); @@ -348,7 +337,7 @@ else if (!isMappingOnlyFactory()) if (isMappingOnlyFactory()) for (int i = 0; i < cls.length; i++) ser.removeMetaData(pr.getMetaData(cls[i], envLoader, - false)); + false)); serialize(ser, null, Serializer.PRETTY); } if (qqs != null && !qqs.isEmpty()) { @@ -369,14 +358,14 @@ else if (!isMappingOnlyFactory()) * null if no existing files */ private Set assignDefaultMetaDataFiles(ClassMetaData[] metas, - QueryMetaData[] queries, SequenceMetaData[] seqs, int mode, - Map clsNames) { + QueryMetaData[] queries, SequenceMetaData[] seqs, int mode, + Map clsNames) { Set files = null; for (int i = 0; i < metas.length; i++) { if (getSourceFile(metas[i]) == null) setSourceFile(metas[i], defaultSourceFile(metas[i])); if ((AccessController.doPrivileged(J2DoPrivHelper - .existsAction(getSourceFile(metas[i])))).booleanValue()) { + .existsAction(getSourceFile(metas[i])))).booleanValue()) { if (files == null) files = new HashSet(); files.add(getSourceFile(metas[i])); @@ -384,16 +373,16 @@ private Set assignDefaultMetaDataFiles(ClassMetaData[] metas, } for (int i = 0; i < queries.length; i++) { if (queries[i].getSourceMode() == MODE_QUERY - || (mode & queries[i].getSourceMode()) == 0) + || (mode & queries[i].getSourceMode()) == 0) continue; if (queries[i].getSourceFile() == null) { File defaultFile = defaultSourceFile(queries[i], clsNames); queries[i].setSource(defaultFile, queries[i].getSourceScope(), queries[i].getSourceType(), - defaultFile == null ? "" : defaultFile.getPath()); + defaultFile == null ? "" : defaultFile.getPath()); } if ((AccessController.doPrivileged( - J2DoPrivHelper.existsAction(queries[i].getSourceFile()))) - .booleanValue()) { + J2DoPrivHelper.existsAction(queries[i].getSourceFile()))) + .booleanValue()) { if (files == null) files = new HashSet(); files.add(queries[i].getSourceFile()); @@ -403,10 +392,10 @@ private Set assignDefaultMetaDataFiles(ClassMetaData[] metas, for (int i = 0; i < seqs.length; i++) { if (getSourceFile(seqs[i]) == null) setSourceFile(seqs[i], defaultSourceFile(seqs[i], - clsNames)); + clsNames)); if ((AccessController.doPrivileged( - J2DoPrivHelper.existsAction(getSourceFile(seqs[i])))) - .booleanValue()) { + J2DoPrivHelper.existsAction(getSourceFile(seqs[i])))) + .booleanValue()) { if (files == null) files = new HashSet(); files.add(getSourceFile(seqs[i])); @@ -424,7 +413,7 @@ private Set assignDefaultMetaDataFiles(ClassMetaData[] metas, * null if no existing files */ private Set assignDefaultQueryFiles(QueryMetaData[] queries, - Map clsNames) { + Map clsNames) { Set files = null; for (int i = 0; i < queries.length; i++) { if (queries[i].getSourceMode() != MODE_QUERY) @@ -432,11 +421,11 @@ private Set assignDefaultQueryFiles(QueryMetaData[] queries, if (queries[i].getSourceFile() == null) { File defaultFile = defaultSourceFile(queries[i], clsNames); queries[i].setSource(defaultFile, queries[i].getSourceScope(), queries[i].getSourceType(), - defaultFile == null ? "" : defaultFile.getPath()); + defaultFile == null ? "" : defaultFile.getPath()); } if ((AccessController.doPrivileged( - J2DoPrivHelper.existsAction(queries[i].getSourceFile()))) - .booleanValue()) { + J2DoPrivHelper.existsAction(queries[i].getSourceFile()))) + .booleanValue()) { if (files == null) files = new HashSet(); files.add(queries[i].getSourceFile()); @@ -458,7 +447,7 @@ protected boolean isMappingOnlyFactory() { */ protected void parse(MetaDataParser parser, Collection files) { try { - for (Iterator itr = files.iterator(); itr.hasNext();) + for (Iterator itr = files.iterator(); itr.hasNext(); ) parser.parse((File) itr.next()); } catch (IOException ioe) { throw new GeneralException(ioe); @@ -488,7 +477,7 @@ protected boolean isParseTopDown() { * Tell the given serialier to write its metadatas. */ protected void serialize(MetaDataSerializer ser, Map output, - int flags) { + int flags) { try { if (output == null) ser.serialize(flags); @@ -504,11 +493,11 @@ protected void serialize(MetaDataSerializer ser, Map output, */ protected void backupAndDelete(Collection files) { File file; - for (Iterator itr = files.iterator(); itr.hasNext();) { + for (Iterator itr = files.iterator(); itr.hasNext(); ) { file = (File) itr.next(); if (Files.backup(file, false) != null) AccessController - .doPrivileged(J2DoPrivHelper.deleteAction(file)); + .doPrivileged(J2DoPrivHelper.deleteAction(file)); } } @@ -530,8 +519,8 @@ protected File getSourceFile(ClassMetaData meta) { * Set the current source file of the given metadata. */ protected void setSourceFile(ClassMetaData meta, File sourceFile) { - meta.setSource(sourceFile, meta.getSourceType(), sourceFile != null ? - sourceFile.getPath() : ""); + meta.setSource(sourceFile, meta.getSourceType(), sourceFile != null ? + sourceFile.getPath() : ""); } /** @@ -546,7 +535,7 @@ protected File getSourceFile(SequenceMetaData meta) { */ protected void setSourceFile(SequenceMetaData meta, File sourceFile) { meta.setSource(sourceFile, meta.getSourceScope(), - meta.getSourceType()); + meta.getSourceType()); } /** @@ -558,19 +547,19 @@ protected void setSourceFile(SequenceMetaData meta, File sourceFile) { * Return a default file for the given query. */ protected abstract File defaultSourceFile(QueryMetaData query, - Map clsNames); + Map clsNames); /** * Return a default file for the given sequence. */ protected abstract File defaultSourceFile(SequenceMetaData seq, - Map clsNames); + Map clsNames); /** * Create a new metadata parser. * * @param loading if true, this will be the cached parser used for - * loading metadata + * loading metadata */ protected abstract Parser newParser(boolean loading); @@ -590,14 +579,14 @@ protected abstract File defaultSourceFile(SequenceMetaData seq, * @param clsNames map of class names to metadatas */ protected ClassMetaData getDefiningMetaData(QueryMetaData query, - Map clsNames) { + Map clsNames) { Class def = query.getDefiningType(); if (def != null) return (ClassMetaData) clsNames.get(def.getName()); Map.Entry entry; String pkg; - for (Iterator itr = clsNames.entrySet().iterator(); itr.hasNext();) { + for (Iterator itr = clsNames.entrySet().iterator(); itr.hasNext(); ) { entry = (Map.Entry) itr.next(); pkg = Strings.getPackageName((String) entry.getKey()); if (pkg.length() == 0) @@ -606,8 +595,8 @@ protected ClassMetaData getDefiningMetaData(QueryMetaData query, return null; } - public Set getPersistentTypeNames(boolean devpath, - ClassLoader envLoader) { + public Set getPersistentTypeNames(boolean devpath, + ClassLoader envLoader) { // some configured locations might be implicit in spec, so return // null if we don't find any classes, rather than if we don't have // any locations @@ -616,20 +605,20 @@ public Set getPersistentTypeNames(boolean devpath, try { ClassLoader loader = repos.getConfiguration(). - getClassResolverInstance().getClassLoader(getClass(), - envLoader); + getClassResolverInstance().getClassLoader(getClass(), + envLoader); long start = System.currentTimeMillis(); Set names = parsePersistentTypeNames(loader); if (names.isEmpty() && devpath) scan(new ClasspathMetaDataIterator(null, newMetaDataFilter()), - newClassArgParser(), names, false, null); + newClassArgParser(), names, false, null); else // we don't cache a full dev cp scan _typeNames = names; if (log.isTraceEnabled()) log.trace(_loc.get("found-pcs", String.valueOf(names.size()), - String.valueOf(System.currentTimeMillis() - start))); + String.valueOf(System.currentTimeMillis() - start))); return (names.isEmpty()) ? null : names; } catch (IOException ioe) { throw new GeneralException(ioe); @@ -640,29 +629,29 @@ public Set getPersistentTypeNames(boolean devpath, * Parse persistent type names. */ protected Set parsePersistentTypeNames(ClassLoader loader) - throws IOException { + throws IOException { ClassArgParser cparser = newClassArgParser(); String[] clss; Set names = new HashSet(); if (files != null) { File file; - for (Iterator itr = files.iterator(); itr.hasNext();) { + for (Iterator itr = files.iterator(); itr.hasNext(); ) { file = (File) itr.next(); if ((AccessController.doPrivileged(J2DoPrivHelper - .isDirectoryAction(file))).booleanValue()) { + .isDirectoryAction(file))).booleanValue()) { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-directory", file)); scan(new FileMetaDataIterator(file, newMetaDataFilter()), - cparser, names, true, file); + cparser, names, true, file); } else if (file.getName().endsWith(".jar")) { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-jar", file)); try { ZipFile zFile = AccessController - .doPrivileged(J2DoPrivHelper - .newZipFileAction(file)); + .doPrivileged(J2DoPrivHelper + .newZipFileAction(file)); scan(new ZipFileMetaDataIterator(zFile, - newMetaDataFilter()), cparser, names, true, file); + newMetaDataFilter()), cparser, names, true, file); } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } @@ -670,17 +659,17 @@ protected Set parsePersistentTypeNames(ClassLoader loader) if (log.isTraceEnabled()) log.trace(_loc.get("scanning-file", file)); clss = cparser.parseTypeNames(new FileMetaDataIterator - (file)); + (file)); List newNames = Arrays.asList(clss); if (log.isTraceEnabled()) log.trace(_loc.get("scan-found-names", newNames, file)); names.addAll(newNames); File f = AccessController - .doPrivileged(J2DoPrivHelper - .getAbsoluteFileAction(file)); + .doPrivileged(J2DoPrivHelper + .getAbsoluteFileAction(file)); try { mapPersistentTypeNames(AccessController - .doPrivileged(J2DoPrivHelper.toURLAction(f)), clss); + .doPrivileged(J2DoPrivHelper.toURLAction(f)), clss); } catch (PrivilegedActionException pae) { throw (FileNotFoundException) pae.getException(); } @@ -689,22 +678,22 @@ protected Set parsePersistentTypeNames(ClassLoader loader) } URL url; if (urls != null) { - for (Iterator itr = urls.iterator(); itr.hasNext();) { + for (Iterator itr = urls.iterator(); itr.hasNext(); ) { url = (URL) itr.next(); if ("file".equals(url.getProtocol())) { File file = AccessController - .doPrivileged(J2DoPrivHelper - .getAbsoluteFileAction(new File(url.getFile()))); + .doPrivileged(J2DoPrivHelper + .getAbsoluteFileAction(new File(url.getFile()))); if (files != null && files.contains(file)) { continue; } else if ((AccessController - .doPrivileged(J2DoPrivHelper.isDirectoryAction(file))) - .booleanValue()) { + .doPrivileged(J2DoPrivHelper.isDirectoryAction(file))) + .booleanValue()) { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-directory", file)); scan( - new FileMetaDataIterator(file, newMetaDataFilter()), - cparser, names, true, file); + new FileMetaDataIterator(file, newMetaDataFilter()), + cparser, names, true, file); continue; } } @@ -717,7 +706,7 @@ protected Set parsePersistentTypeNames(ClassLoader loader) final Object vfsContent = conn.getContent(); final URL finalUrl = url; File file = AccessController.doPrivileged(new PrivilegedAction() { - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) public File run() { try { Class virtualFileClass = Class.forName("org.jboss.vfs.VirtualFile"); @@ -739,51 +728,59 @@ public File run() { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-jar-url", url)); scan(new ZipFileMetaDataIterator(url, - newMetaDataFilter()), cparser, names, true, url); + newMetaDataFilter()), cparser, names, true, url); } else { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-jar-url", url)); scan(new JarFileURLMetaDataIterator(url, - newMetaDataFilter()), cparser, names, true, url); - } + newMetaDataFilter()), cparser, names, true, url); + } } else if (url.getPath().endsWith(".jar")) { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-jar-at-url", url)); try { InputStream is = (InputStream) - AccessController.doPrivileged( - J2DoPrivHelper.openStreamAction(url)); + AccessController.doPrivileged( + J2DoPrivHelper.openStreamAction(url)); scan(new ZipStreamMetaDataIterator( - new ZipInputStream(is), - newMetaDataFilter()), cparser, names, true, url); + new ZipInputStream(is), + newMetaDataFilter()), cparser, names, true, url); } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } + } else if ("bundle".equals(url.getProtocol())) { + + if (log.isTraceEnabled()) { + log.trace(_loc.get("scanning-osgi-bundle", url)); + } + MetaDataIterator mdi = new OSGiBundleMetaDataIterator(url, newMetaDataFilter()); + scan(mdi, cparser, names, true, url); + } else { // Open an InputStream from the URL and sniff for a zip header. If it is, then this is // a URL with a jar-formated InputStream, as per the JPA specification. Otherwise, fall back // to URLMetaDataIterator. - BufferedInputStream is = null; - + BufferedInputStream is = null; + try { is = new BufferedInputStream((InputStream) AccessController. - doPrivileged(J2DoPrivHelper.openStreamAction(url))); + doPrivileged(J2DoPrivHelper.openStreamAction(url))); } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } - + // Check for zip header magic 0x50 0x4b 0x03 0x04 is.mark(0); - boolean zipHeaderMatch = is.read() == 0x50 && is.read() == 0x4b && is.read() == 0x03 && - is.read() == 0x04; + boolean zipHeaderMatch = is.read() == 0x50 && is.read() == 0x4b && is.read() == 0x03 && + is.read() == 0x04; is.reset(); - + if (zipHeaderMatch) { // The URL provides a Jar-formatted InputStream, consume it with ZipStreamMetaDataIterator if (log.isTraceEnabled()) log.trace(_loc.get("scanning-jar-at-url", url)); scan(new ZipStreamMetaDataIterator(new ZipInputStream(is), newMetaDataFilter()), - cparser, names, true, url); + cparser, names, true, url); } else { // Fall back to URLMetaDataIterator if (log.isTraceEnabled()) @@ -794,29 +791,29 @@ public File run() { log.trace(_loc.get("scan-found-names", newNames, url)); names.addAll(newNames); mapPersistentTypeNames(url, clss); - } + } } } } if (rsrcs != null) { String rsrc; MetaDataIterator mitr; - for (Iterator itr = rsrcs.iterator(); itr.hasNext();) { + for (Iterator itr = rsrcs.iterator(); itr.hasNext(); ) { rsrc = (String) itr.next(); if (rsrc.endsWith(".jar")) { url = AccessController.doPrivileged( - J2DoPrivHelper.getResourceAction(loader, rsrc)); + J2DoPrivHelper.getResourceAction(loader, rsrc)); if (url != null) { if (log.isTraceEnabled()) log.trace(_loc.get("scanning-jar-stream-url", url)); try { InputStream is = (InputStream) - AccessController.doPrivileged( - J2DoPrivHelper.openStreamAction(url)); + AccessController.doPrivileged( + J2DoPrivHelper.openStreamAction(url)); scan(new ZipStreamMetaDataIterator - (new ZipInputStream(is), - newMetaDataFilter()), cparser, names, true, - url); + (new ZipInputStream(is), + newMetaDataFilter()), cparser, names, true, + url); } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } @@ -828,11 +825,11 @@ public File run() { OpenJPAConfiguration conf = repos.getConfiguration(); Map peMap = null; if (conf instanceof OpenJPAConfigurationImpl) - peMap = ((OpenJPAConfigurationImpl)conf).getPersistenceEnvironment(); + peMap = ((OpenJPAConfigurationImpl) conf).getPersistenceEnvironment(); URL puUrl = peMap == null ? null : (URL) peMap.get(PERSISTENCE_UNIT_ROOT_URL); - List mappingFileNames = - peMap == null ? null : (List) peMap.get(MAPPING_FILE_NAMES); - List jars = peMap == null ? null : (List)peMap.get(JAR_FILE_URLS); + List mappingFileNames = + peMap == null ? null : (List) peMap.get(MAPPING_FILE_NAMES); + List jars = peMap == null ? null : (List) peMap.get(JAR_FILE_URLS); String puUrlString = puUrl == null ? null : puUrl.toString(); if (log.isTraceEnabled()) log.trace(_loc.get("pu-root-url", puUrlString)); @@ -854,7 +851,7 @@ public File run() { if (log.isTraceEnabled()) log.trace(_loc.get("resource-url", urlString)); if (peMap != null) { - //OPENJPA-2102: decode the URL to remove such things a spaces (' ') encoded as '%20' + //OPENJPA-2102: decode the URL to remove such things a spaces (' ') encoded as '%20' if (puUrlString != null && decode(urlString).indexOf(decode(puUrlString)) != -1) { urls.add(url); } else if (puORMUrl != null && puORMUrl.equals(url)) { @@ -887,7 +884,7 @@ public File run() { for (Object obj : urls) { url = (URL) obj; clss = cparser.parseTypeNames(new URLMetaDataIterator - (url)); + (url)); List newNames = Arrays.asList(clss); if (log.isTraceEnabled()) log.trace(_loc.get("scan-found-names", newNames, @@ -901,14 +898,14 @@ public File run() { if (cpath != null) { String[] dirs = (String[]) cpath.toArray(new String[cpath.size()]); scan(new ClasspathMetaDataIterator(dirs, newMetaDataFilter()), - cparser, names, true, dirs); + cparser, names, true, dirs); } if (types != null) names.addAll(types); if (log.isTraceEnabled()) log.trace(_loc.get("parse-found-names", names)); - + return names; } @@ -916,8 +913,8 @@ public File run() { * Scan for persistent type names using the given metadata iterator. */ private void scan(MetaDataIterator mitr, ClassArgParser cparser, Set names, - boolean mapNames, Object debugContext) - throws IOException { + boolean mapNames, Object debugContext) + throws IOException { Map map; try { map = cparser.mapTypeNames(mitr); @@ -926,76 +923,77 @@ private void scan(MetaDataIterator mitr, ClassArgParser cparser, Set names, } Map.Entry entry; - for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { + for (Iterator itr = map.entrySet().iterator(); itr.hasNext(); ) { entry = (Map.Entry) itr.next(); if (mapNames) mapPersistentTypeNames(entry.getKey(), (String[]) - entry.getValue()); + entry.getValue()); List newNames = Arrays.asList((String[]) entry.getValue()); if (log.isTraceEnabled()) log.trace(_loc.get("scan-found-names", newNames, debugContext)); names.addAll(newNames); } } - + /** * Decodes a URL-encoded path string. For example, an encoded * space (%20) is decoded into a normal space (' ') character. * Added via OPENJPA-2102. + * * @param String encoded - the encoded URL string * @return String decoded - the decoded string. */ public static String decode(String s) { - if (s == null) { - return null; - } - - int i = s.indexOf('%'); - if (i == -1) { - return s; - } - - StringBuilder builder = new StringBuilder(); - int begin = 0; + if (s == null) { + return null; + } - do { - builder.append(s, begin, i); - begin = i + 3; + int i = s.indexOf('%'); + if (i == -1) { + return s; + } - char ch = (char) Integer.parseInt(s.substring(i + 1, begin), 16); + StringBuilder builder = new StringBuilder(); + int begin = 0; - if ((ch & 0x80) != 0) { - // Decode "modified UTF-8". + do { + builder.append(s, begin, i); + begin = i + 3; - if (s.charAt(begin++) != '%') { - throw new IllegalArgumentException(); - } + char ch = (char) Integer.parseInt(s.substring(i + 1, begin), 16); - char ch2 = (char) Integer.parseInt(s.substring(begin, begin + 2), 16); - begin += 2; + if ((ch & 0x80) != 0) { + // Decode "modified UTF-8". - if ((ch & 0xe0) == 0xc0) { - ch = (char) (((ch & 0x1f) << 6) | (ch2 & 0x3f)); - } else if ((ch & 0xf0) == 0xe0) { if (s.charAt(begin++) != '%') { - throw new IllegalArgumentException(); + throw new IllegalArgumentException(); } - char ch3 = (char) Integer.parseInt(s.substring(begin, begin + 2), 16); + char ch2 = (char) Integer.parseInt(s.substring(begin, begin + 2), 16); begin += 2; - ch = (char) (((ch & 0x0f) << 12) | ((ch2 & 0x3f) << 6) | (ch3 & 0x3f)); - } else { - throw new IllegalArgumentException(); - } - } + if ((ch & 0xe0) == 0xc0) { + ch = (char) (((ch & 0x1f) << 6) | (ch2 & 0x3f)); + } else if ((ch & 0xf0) == 0xe0) { + if (s.charAt(begin++) != '%') { + throw new IllegalArgumentException(); + } + + char ch3 = (char) Integer.parseInt(s.substring(begin, begin + 2), 16); + begin += 2; + + ch = (char) (((ch & 0x0f) << 12) | ((ch2 & 0x3f) << 6) | (ch3 & 0x3f)); + } else { + throw new IllegalArgumentException(); + } + } - builder.append(ch); - } while ((i = s.indexOf('%', begin)) != -1); + builder.append(ch); + } while ((i = s.indexOf('%', begin)) != -1); - builder.append(s, begin, s.length()); + builder.append(s, begin, s.length()); - return builder.toString(); + return builder.toString(); } /** @@ -1021,7 +1019,7 @@ public void clear() { * Internal parser interface. */ public static interface Parser - extends MetaDataParser { + extends MetaDataParser { /** * Returns the repository for this parser. If none has been set, @@ -1039,7 +1037,7 @@ public static interface Parser * Internal serializer interface. */ public static interface Serializer - extends MetaDataSerializer { + extends MetaDataSerializer { /** * The serialization mode according to the expected document type. The @@ -1071,6 +1069,6 @@ public static interface Serializer * Add all components in the given repository to the set to be * serialized. */ - public void addAll (MetaDataRepository repos); + public void addAll(MetaDataRepository repos); } } diff --git a/openjpa-lib/pom.xml b/openjpa-lib/pom.xml index d6e87f4aa9..188974f558 100644 --- a/openjpa-lib/pom.xml +++ b/openjpa-lib/pom.xml @@ -78,7 +78,12 @@ org.apache.geronimo.specs geronimo-validation_1.0_spec provided - + + + org.osgi + org.osgi.core + 4.2.0 + diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java new file mode 100644 index 0000000000..7f86ffbe40 --- /dev/null +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java @@ -0,0 +1,130 @@ +/* + * 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.lib.meta; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +import java.io.*; +import java.net.URL; +import java.util.Enumeration; +import java.util.NoSuchElementException; + +/** + * Created by andrei on 24.07.2014. + */ +public class OSGiBundleMetaDataIterator implements MetaDataIterator, MetaDataFilter.Resource { + + private InputStream stream; + private Bundle bundle; + private Enumeration entries; + private MetaDataFilter filter; + private URL entry; + private URL last; + private byte[] buf; + + public OSGiBundleMetaDataIterator(URL bundleUrl, MetaDataFilter filter) { + + BundleContext ctx = FrameworkUtil.getBundle(OSGiBundleMetaDataIterator.class).getBundleContext(); + long bundleId = Long.parseLong(bundleUrl.getHost().substring(0, bundleUrl.getHost().indexOf("."))); + this.bundle = ctx.getBundle(bundleId); + entries = this.bundle.findEntries("/", "*.class", true); + this.filter = filter; + + } + + @Override + public boolean hasNext() throws IOException { + + if (entries == null) { + return false; + } + + if (entry != null) { + return true; + } + + last = null; + buf = null; + + if (!entries.hasMoreElements()) { + return false; + } + + URL tmp; + while ( entry == null && (entries.hasMoreElements() && (tmp = this.entries.nextElement()) != null)) { + entry = tmp; + stream = entry.openStream(); + if (filter != null && !this.filter.matches(this)) { + entry = null; + } + + } + + return entry != null; + + } + + @Override + public Object next() throws IOException { + + if (!hasNext()) { + throw new NoSuchElementException(); + } + + String name = entry.toString(); + last = entry; + entry = null; + + return name; + } + + @Override + public InputStream getInputStream() throws IOException { + if (last == null) + throw new IllegalStateException(); + + return last.openStream(); + } + + @Override + public File getFile() throws IOException { + return null; + } + + @Override + public void close() { + } + + @Override + public String getName() { + return entry.toString(); + } + + @Override + public byte[] getContent() throws IOException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + for (int r; (r = stream.read(buf)) != -1; bout.write(buf, 0, r)) ; + buf = bout.toByteArray(); + stream.close(); + return buf; + } +} From d41e012b61cdebccd0eaf7cba6a710e3001b0fd9 Mon Sep 17 00:00:00 2001 From: artaxerxe Date: Wed, 9 Jun 2021 15:15:03 +0300 Subject: [PATCH 5/7] fixed merge conflict. --- .../apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java index 5f82cff8d9..7f86ffbe40 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java @@ -61,11 +61,6 @@ public boolean hasNext() throws IOException { return true; } -<<<<<<< HEAD -// if (buf == null && last != null) -// _stream.closeEntry(); -======= ->>>>>>> refs/remotes/origin/2.3.0-osgi_fixed last = null; buf = null; From 266a27db268a1cd526db1b8957a1164ee8adc516 Mon Sep 17 00:00:00 2001 From: artaxerxe Date: Wed, 9 Jun 2021 15:15:03 +0300 Subject: [PATCH 6/7] fixed dependency. --- .../org/apache/openjpa/meta/AbstractCFMetaDataFactory.java | 1 + .../apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java index 0402b600a1..6b06ad7656 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java @@ -53,6 +53,7 @@ import org.apache.openjpa.lib.meta.MetaDataIterator; import org.apache.openjpa.lib.meta.MetaDataParser; import org.apache.openjpa.lib.meta.MetaDataSerializer; +import org.apache.openjpa.lib.meta.OSGiBundleMetaDataIterator; import org.apache.openjpa.lib.meta.ResourceMetaDataIterator; import org.apache.openjpa.lib.meta.URLMetaDataIterator; import org.apache.openjpa.lib.meta.ZipFileMetaDataIterator; diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java index 5f82cff8d9..7f86ffbe40 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/OSGiBundleMetaDataIterator.java @@ -61,11 +61,6 @@ public boolean hasNext() throws IOException { return true; } -<<<<<<< HEAD -// if (buf == null && last != null) -// _stream.closeEntry(); -======= ->>>>>>> refs/remotes/origin/2.3.0-osgi_fixed last = null; buf = null; From 2cf0eaca2132d9f2a5c72d56ddf67f26a8f465d8 Mon Sep 17 00:00:00 2001 From: artaxerxe Date: Fri, 11 Jun 2021 12:48:13 +0300 Subject: [PATCH 7/7] Revert "OPENJPA-2745: Clean up try-catch implementation for DB2Dictionary" This reverts commit fadcf7652fb8660b7374187bc5e50e636772a6ab. --- .../openjpa/jdbc/sql/DB2Dictionary.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java index 523b9ae543..eaea440e3a 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java @@ -1023,22 +1023,30 @@ public byte[] getBytes(ResultSet rs, int column) return (byte[]) rs.getObject(column); } - int type = rs.getMetaData().getColumnType(column); - switch (type) { - case Types.BLOB: - Blob blob = getBlob(rs, column); - if (blob == null) { - return null; - } - - int length = (int) blob.length(); - if (length == 0) { - return null; - } - return blob.getBytes(1, length); - case Types.BINARY: - default: + // At this point we don't have any idea if the DB2 column was defined as + // a blob or if it was defined as CHAR for BIT DATA. + // First try as a blob, if that doesn't work, then try as CHAR for BIT DATA + // If that doesn't work, then go ahead and throw the first exception + try { + Blob blob = getBlob(rs, column); + if (blob == null) { + return null; + } + + int length = (int) blob.length(); + if (length == 0) { + return null; + } + + return blob.getBytes(1, length); + } + catch (SQLException e) { + try { return rs.getBytes(column); + } + catch (SQLException e2) { + throw e; + } } }