/*******************************************************************************
* Copyright (c) 2008-2010 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.bndtools.builder.classpath;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
import aQute.lib.io.IO;
class ClasspathContainerSerializationHelper<C extends IClasspathContainer> {
C readClasspathContainer(File file) throws IOException, ClassNotFoundException {
try (InputStream in = IO.stream(file)) {
return readClasspathContainer(in);
}
}
C readClasspathContainer(InputStream in) throws IOException, ClassNotFoundException {
try (ObjectInputStream ois = new ObjectResolver(in)) {
@SuppressWarnings("unchecked")
C container = (C) ois.readObject();
return container;
}
}
private static final class ObjectResolver extends ObjectInputStream {
ObjectResolver(InputStream in) throws IOException {
super(in);
enableResolveObject(true);
}
@Override
protected Object resolveObject(Object o) throws IOException {
if (o instanceof ProjectEntryReplace) {
return ((ProjectEntryReplace) o).getEntry();
} else if (o instanceof LibraryEntryReplace) {
return ((LibraryEntryReplace) o).getEntry();
} else if (o instanceof ClasspathAttributeReplace) {
return ((ClasspathAttributeReplace) o).getAttribute();
} else if (o instanceof AccessRuleReplace) {
return ((AccessRuleReplace) o).getAccessRule();
} else if (o instanceof PathReplace) {
return ((PathReplace) o).getPath();
}
return super.resolveObject(o);
}
}
void writeClasspathContainer(C container, File file) throws IOException {
try (OutputStream out = IO.outputStream(file)) {
writeClasspathContainer(container, out);
}
}
void writeClasspathContainer(C container, OutputStream out) throws IOException {
try (ObjectOutputStream oos = new ObjectReplacer(out)) {
oos.writeObject(container);
}
}
private static final class ObjectReplacer extends ObjectOutputStream {
ObjectReplacer(OutputStream out) throws IOException {
super(out);
enableReplaceObject(true);
}
@Override
protected Object replaceObject(Object o) throws IOException {
if (o instanceof IClasspathEntry) {
IClasspathEntry e = (IClasspathEntry) o;
if (e.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
return new ProjectEntryReplace(e);
} else if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
return new LibraryEntryReplace(e);
}
} else if (o instanceof IClasspathAttribute) {
return new ClasspathAttributeReplace((IClasspathAttribute) o);
} else if (o instanceof IAccessRule) {
return new AccessRuleReplace((IAccessRule) o);
} else if (o instanceof IPath) {
return new PathReplace((IPath) o);
}
return super.replaceObject(o);
}
}
/**
* A library IClasspathEntry replacement used for object serialization
*/
static final class LibraryEntryReplace implements Serializable {
private static final long serialVersionUID = 1L;
private final IPath path;
private final IPath sourceAttachmentPath;
private final IPath sourceAttachmentRootPath;
private final IAccessRule[] accessRules;
private final IClasspathAttribute[] extraAttributes;
private final boolean exported;
LibraryEntryReplace(IClasspathEntry entry) {
this.path = entry.getPath();
this.sourceAttachmentPath = entry.getSourceAttachmentPath();
this.sourceAttachmentRootPath = entry.getSourceAttachmentRootPath();
this.accessRules = entry.getAccessRules();
this.extraAttributes = entry.getExtraAttributes();
this.exported = entry.isExported();
}
IClasspathEntry getEntry() {
return JavaCore.newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, accessRules, extraAttributes, exported);
}
}
/**
* A project IClasspathEntry replacement used for object serialization
*/
static final class ProjectEntryReplace implements Serializable {
private static final long serialVersionUID = 1L;
private final IPath path;
private final IAccessRule[] accessRules;
private final boolean combineAccessRules;
private final IClasspathAttribute[] extraAttributes;
private final boolean exported;
ProjectEntryReplace(IClasspathEntry entry) {
this.path = entry.getPath();
this.accessRules = entry.getAccessRules();
this.combineAccessRules = entry.combineAccessRules();
this.extraAttributes = entry.getExtraAttributes();
this.exported = entry.isExported();
}
IClasspathEntry getEntry() {
return JavaCore.newProjectEntry(path, accessRules, combineAccessRules, extraAttributes, exported);
}
}
/**
* An IClasspathAttribute replacement used for object serialization
*/
static final class ClasspathAttributeReplace implements Serializable {
private static final long serialVersionUID = 1L;
private final String name;
private final String value;
ClasspathAttributeReplace(IClasspathAttribute attribute) {
this.name = attribute.getName();
this.value = attribute.getValue();
}
IClasspathAttribute getAttribute() {
return JavaCore.newClasspathAttribute(name, value);
}
}
/**
* An IAccessRule replacement used for object serialization
*/
static final class AccessRuleReplace implements Serializable {
private static final long serialVersionUID = 1L;
private final IPath pattern;
private final int kind;
AccessRuleReplace(IAccessRule accessRule) {
pattern = accessRule.getPattern();
kind = accessRule.getKind() | (accessRule.ignoreIfBetter() ? IAccessRule.IGNORE_IF_BETTER : 0);
}
IAccessRule getAccessRule() {
return JavaCore.newAccessRule(pattern, kind);
}
}
/**
* An IPath replacement used for object serialization
*/
static final class PathReplace implements Serializable {
private static final long serialVersionUID = 1L;
private final String path;
PathReplace(IPath path) {
this.path = path.toPortableString();
}
IPath getPath() {
return Path.fromPortableString(path);
}
}
}