/* * 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.ode.bpel.o; import javax.xml.namespace.QName; import java.io.*; import java.util.Arrays; /** * Header written at the beginning of every compiled BPEL object file. */ public class Serializer { public static final byte[] MAGIC_NUMBER_OFH_20040908 = new byte[] { 0x55, '5', 'S', 0x00, 'O', 'F', 'H', 0x20, 0x04, 0x09, 0x08 }; public static final byte[] MAGIC_NUMBER_OFH_20061101 = new byte[] { 0x55, '5', 'S', 0x00, 'O', 'F', 'H', 0x20, 0x06, 0x11, 0x01 }; public static final byte[] MAGIC_NUMBER = MAGIC_NUMBER_OFH_20061101; public static final short FORMAT_SERIALIZED_JAVA14 = 0x01; // START PERSISTED FIELDS public final byte[] magic = new byte[MAGIC_NUMBER.length]; /** Compiled Process representation format. */ public short format; /** Time of compilation (system local time). */ public long compileTime; /** Deprecated, only one process per file. */ public final int numProcesses = 1; public InputStream _inputStream; public String guid; // public OProcess _oprocess; public QName type; // END PERSISTED FIELDS public Serializer(long compileTime) { System.arraycopy(MAGIC_NUMBER, 0, magic, 0, MAGIC_NUMBER.length); this.format = FORMAT_SERIALIZED_JAVA14; this.compileTime = compileTime; } public Serializer() {} public Serializer(InputStream inputStream) throws IOException { _inputStream = inputStream; read(inputStream); } public void read(InputStream is) throws IOException { DataInputStream oin = new DataInputStream(is); byte[] magic = new byte[MAGIC_NUMBER.length]; oin.read(magic, 0, magic.length); if (Arrays.equals(MAGIC_NUMBER_OFH_20040908, magic)) { // Old format requires us to read the OModel to get the type and guid. this.format = oin.readShort(); this.compileTime = oin.readLong(); oin.readInt(); ObjectInputStream ois = new CustomObjectInputStream(_inputStream); OProcess oprocess; try { oprocess = (OProcess) ois.readObject(); } catch (ClassNotFoundException e) { throw new IOException("DataStream Error"); } this.type = new QName(oprocess.targetNamespace, oprocess.processName); this.guid = "OLD-FORMAT-NO-GUID"; return; } // The current (most recent) scheme if (Arrays.equals(MAGIC_NUMBER, magic)) { this.format = oin.readShort(); this.compileTime = oin.readLong(); this.guid = oin.readUTF(); String tns = oin.readUTF(); String name = oin.readUTF(); this.type = new QName(tns, name); return; } throw new IOException("Unrecognized file format (bad magic number)."); } public void writeOProcess(OProcess process, OutputStream os) throws IOException { DataOutputStream out = new DataOutputStream(os); out.write(MAGIC_NUMBER); out.writeShort(format); out.writeLong(compileTime); out.writeUTF(process.guid); out.writeUTF(process.targetNamespace); out.writeUTF(process.processName); out.flush(); ObjectOutputStream oos = new CustomObjectOutputStream(os); oos.writeObject(process); oos.flush(); } public OProcess readOProcess() throws IOException, ClassNotFoundException { // if (_oprocess != null) // return _oprocess; ObjectInputStream ois = new CustomObjectInputStream(_inputStream); OProcess oprocess; try { oprocess = (OProcess) ois.readObject(); } catch (ClassNotFoundException e) { throw new IOException("DataStream Error"); } return oprocess; } static class CustomObjectOutputStream extends ObjectOutputStream { /** * @param out * @throws IOException */ public CustomObjectOutputStream(OutputStream out) throws IOException { super(out); enableReplaceObject(true); } protected Object replaceObject(Object obj) throws IOException{ if(obj instanceof QName){ QName q = (QName)obj; return new OQName(q.getNamespaceURI(), q.getLocalPart(), q.getPrefix()); } return super.replaceObject(obj); } } static class CustomObjectInputStream extends ObjectInputStream { /** * @param in * @throws IOException */ public CustomObjectInputStream(InputStream in) throws IOException { super(in); enableResolveObject(true); } protected Object resolveObject(Object obj) throws IOException { if(obj instanceof OQName){ OQName q = (OQName)obj; return new QName(q.uri, q.local, q.prefix); } return super.resolveObject(obj); } /** * Override coverts old class names into new class names to preserve compatibility with * pre-Apache namespaces. */ @Override protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { ObjectStreamClass read = super.readClassDescriptor(); if (read.getName().startsWith("com.fs.pxe.")) { return ObjectStreamClass.lookup(Class.forName(read.getName().replace("com.fs.pxe.", "org.apache.ode."))); } if (read.getName().startsWith("com.fs.utils.")) { return ObjectStreamClass.lookup(Class.forName(read.getName().replace("com.fs.utils.", "org.apache.ode.utils."))); } return read; } } static class OQName implements Serializable{ private static final long serialVersionUID = 1L; final String local; final String uri; final String prefix; OQName(String uri, String local, String prefix){ this.uri = uri; this.local = local; this.prefix = prefix; } } }