Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPENJPA-2521 Cannot load entities from a different bundle in an OSGi environment #1

Open
wants to merge 11 commits into
base: 2.3.x
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -759,6 +760,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
Expand Down
8 changes: 7 additions & 1 deletion openjpa-lib/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-validation_1.0_spec</artifactId>
<scope>provided</scope>
</dependency>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<URL> 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;
}
}