feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data;
|
||||
|
||||
/**
|
||||
* {@link ByteArrayOutputStream} with access to its raw buffer.
|
||||
*/
|
||||
public final class ByteArrayOutputStreamEx extends ByteArrayOutputStream {
|
||||
public ByteArrayOutputStreamEx() {
|
||||
}
|
||||
|
||||
public ByteArrayOutputStreamEx(int size) {
|
||||
super(size);
|
||||
}
|
||||
|
||||
public void set(Base64Data dt,String mimeType) {
|
||||
dt.set(buf,count,mimeType);
|
||||
}
|
||||
|
||||
public byte[] getBuffer() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given {@link InputStream} completely into the buffer.
|
||||
*/
|
||||
public void readFrom(InputStream is) throws IOException {
|
||||
while(true) {
|
||||
if(count==buf.length) {
|
||||
// realllocate
|
||||
byte[] data = new byte[buf.length*2];
|
||||
System.arraycopy(buf,0,data,0,buf.length);
|
||||
buf = data;
|
||||
}
|
||||
|
||||
int sz = is.read(buf,count,buf.length-count);
|
||||
if(sz<0) return;
|
||||
count += sz;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* {@link Stack}-like data structure that allows the following efficient operations:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Push/pop operation.
|
||||
* <li>Duplicate check. When an object that's already in the stack is pushed,
|
||||
* this class will tell you so.
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
* Object equality is their identity equality.
|
||||
*
|
||||
* <p>
|
||||
* This class implements {@link List} for accessing items in the stack,
|
||||
* but {@link List} methods that alter the stack is not supported.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class CollisionCheckStack<E> extends AbstractList<E> {
|
||||
private Object[] data;
|
||||
private int[] next;
|
||||
private int size = 0;
|
||||
|
||||
private boolean latestPushResult = false;
|
||||
|
||||
/**
|
||||
* True if the check shall be done by using the object identity.
|
||||
* False if the check shall be done with the equals method.
|
||||
*/
|
||||
private boolean useIdentity = true;
|
||||
|
||||
// for our purpose, there isn't much point in resizing this as we don't expect
|
||||
// the stack to grow that much.
|
||||
private final int[] initialHash;
|
||||
|
||||
public CollisionCheckStack() {
|
||||
initialHash = new int[17];
|
||||
data = new Object[16];
|
||||
next = new int[16];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false to use {@link Object#equals(Object)} to detect cycles.
|
||||
* This method can be only used when the stack is empty.
|
||||
*/
|
||||
public void setUseIdentity(boolean useIdentity) {
|
||||
this.useIdentity = useIdentity;
|
||||
}
|
||||
|
||||
public boolean getUseIdentity() {
|
||||
return useIdentity;
|
||||
}
|
||||
|
||||
public boolean getLatestPushResult() {
|
||||
return latestPushResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a new object to the stack.
|
||||
*
|
||||
* @return
|
||||
* true if this object has already been pushed
|
||||
*/
|
||||
public boolean push(E o) {
|
||||
if(data.length==size)
|
||||
expandCapacity();
|
||||
|
||||
data[size] = o;
|
||||
int hash = hash(o);
|
||||
boolean r = findDuplicate(o, hash);
|
||||
next[size] = initialHash[hash];
|
||||
initialHash[hash] = size+1;
|
||||
size++;
|
||||
this.latestPushResult = r;
|
||||
return latestPushResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a new object to the stack without making it participate
|
||||
* with the collision check.
|
||||
*/
|
||||
public void pushNocheck(E o) {
|
||||
if(data.length==size)
|
||||
expandCapacity();
|
||||
data[size] = o;
|
||||
next[size] = -1;
|
||||
size++;
|
||||
}
|
||||
|
||||
public boolean findDuplicate(E o) {
|
||||
int hash = hash(o);
|
||||
return findDuplicate(o, hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int index) {
|
||||
return (E)data[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private int hash(Object o) {
|
||||
return ((useIdentity?System.identityHashCode(o):o.hashCode())&0x7FFFFFFF) % initialHash.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops an object from the stack
|
||||
*/
|
||||
public E pop() {
|
||||
size--;
|
||||
Object o = data[size];
|
||||
data[size] = null; // keeping references too long == memory leak
|
||||
int n = next[size];
|
||||
if(n<0) {
|
||||
// pushed by nocheck. no need to update hash
|
||||
} else {
|
||||
int hash = hash(o);
|
||||
assert initialHash[hash]==size+1;
|
||||
initialHash[hash] = n;
|
||||
}
|
||||
return (E)o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top of the stack.
|
||||
*/
|
||||
public E peek() {
|
||||
return (E)data[size-1];
|
||||
}
|
||||
|
||||
private boolean findDuplicate(E o, int hash) {
|
||||
int p = initialHash[hash];
|
||||
while(p!=0) {
|
||||
p--;
|
||||
Object existing = data[p];
|
||||
if (useIdentity) {
|
||||
if(existing==o) return true;
|
||||
} else {
|
||||
if (o.equals(existing)) return true;
|
||||
}
|
||||
p = next[p];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void expandCapacity() {
|
||||
int oldSize = data.length;
|
||||
int newSize = oldSize * 2;
|
||||
Object[] d = new Object[newSize];
|
||||
int[] n = new int[newSize];
|
||||
|
||||
System.arraycopy(data,0,d,0,oldSize);
|
||||
System.arraycopy(next,0,n,0,oldSize);
|
||||
|
||||
data = d;
|
||||
next = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the contents in the stack.
|
||||
*/
|
||||
public void reset() {
|
||||
if(size>0) {
|
||||
size = 0;
|
||||
Arrays.fill(initialHash,0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String that represents the cycle.
|
||||
*/
|
||||
public String getCycleString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i=size()-1;
|
||||
E obj = get(i);
|
||||
sb.append(obj);
|
||||
Object x;
|
||||
do {
|
||||
sb.append(" -> ");
|
||||
x = get(--i);
|
||||
sb.append(x);
|
||||
} while(obj!=x);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.MimeType;
|
||||
import javax.activation.MimeTypeParseException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
/**
|
||||
* {@link Source} implementation backed by {@link DataHandler}.
|
||||
*
|
||||
* <p>
|
||||
* This implementation allows the same {@link Source} to be used
|
||||
* mutliple times.
|
||||
*
|
||||
* <p>
|
||||
* {@link Source} isn't really pluggable. As a consequence,
|
||||
* this implementation is clunky --- weak against unexpected
|
||||
* usage of the class.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class DataSourceSource extends StreamSource {
|
||||
private final DataSource source;
|
||||
|
||||
/**
|
||||
* If null, default to the encoding declaration
|
||||
*/
|
||||
private final String charset;
|
||||
|
||||
// remember the value we returned so that the 2nd invocation
|
||||
// will return the same object, which is what's expeted out of
|
||||
// StreamSource
|
||||
private Reader r;
|
||||
private InputStream is;
|
||||
|
||||
public DataSourceSource(DataHandler dh) throws MimeTypeParseException {
|
||||
this(dh.getDataSource());
|
||||
}
|
||||
|
||||
public DataSourceSource(DataSource source) throws MimeTypeParseException {
|
||||
this.source = source;
|
||||
|
||||
String ct = source.getContentType();
|
||||
if(ct==null) {
|
||||
charset = null;
|
||||
} else {
|
||||
MimeType mimeType = new MimeType(ct);
|
||||
this.charset = mimeType.getParameter("charset");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReader(Reader reader) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputStream(InputStream inputStream) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader getReader() {
|
||||
try {
|
||||
if(charset==null) return null;
|
||||
if(r==null)
|
||||
r = new InputStreamReader(source.getInputStream(),charset);
|
||||
return r;
|
||||
} catch (IOException e) {
|
||||
// argh
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
if(charset!=null) return null;
|
||||
if(is==null)
|
||||
is = source.getInputStream();
|
||||
return is;
|
||||
} catch (IOException e) {
|
||||
// argh
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public DataSource getDataSource() {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
143
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/EditDistance.java
Normal file
143
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/EditDistance.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* Computes the string edit distance.
|
||||
*
|
||||
* <p>
|
||||
* Refer to a computer science text book for the definition
|
||||
* of the "string edit distance".
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public class EditDistance {
|
||||
|
||||
/**
|
||||
* Weak results cache to avoid additional computations.
|
||||
* Because of high complexity caching is required.
|
||||
*/
|
||||
private static final WeakHashMap<AbstractMap.SimpleEntry<String,String>, Integer> CACHE = new WeakHashMap<AbstractMap.SimpleEntry<String, String>, Integer>();
|
||||
|
||||
/**
|
||||
* Computes the edit distance between two strings.
|
||||
*
|
||||
* <p>
|
||||
* The complexity is O(nm) where n=a.length() and m=b.length().
|
||||
*/
|
||||
public static int editDistance( String a, String b ) {
|
||||
// let's check cache
|
||||
AbstractMap.SimpleEntry<String,String> entry = new AbstractMap.SimpleEntry<String, String>(a, b); // using this class to avoid creation of my own which will handle PAIR of values
|
||||
Integer result = null;
|
||||
if (CACHE.containsKey(entry))
|
||||
result = CACHE.get(entry); // looks like we have it
|
||||
|
||||
if (result == null) {
|
||||
result = new EditDistance(a, b).calc();
|
||||
CACHE.put(entry, result); // cache the result
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the string in the <code>group</code> closest to
|
||||
* <code>key</code> and returns it.
|
||||
*
|
||||
* @return null if group.length==0.
|
||||
*/
|
||||
public static String findNearest( String key, String[] group ) {
|
||||
return findNearest(key, Arrays.asList(group));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the string in the <code>group</code> closest to
|
||||
* <code>key</code> and returns it.
|
||||
*
|
||||
* @return null if group.length==0.
|
||||
*/
|
||||
public static String findNearest( String key, Collection<String> group ) {
|
||||
int c = Integer.MAX_VALUE;
|
||||
String r = null;
|
||||
|
||||
for (String s : group) {
|
||||
int ed = editDistance(key,s);
|
||||
if( c>ed ) {
|
||||
c = ed;
|
||||
r = s;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/** cost vector. */
|
||||
private int[] cost;
|
||||
/** back buffer. */
|
||||
private int[] back;
|
||||
|
||||
/** Two strings to be compared. */
|
||||
private final String a,b;
|
||||
|
||||
private EditDistance( String a, String b ) {
|
||||
this.a=a;
|
||||
this.b=b;
|
||||
cost = new int[a.length()+1];
|
||||
back = new int[a.length()+1]; // back buffer
|
||||
|
||||
for( int i=0; i<=a.length(); i++ )
|
||||
cost[i] = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps two buffers.
|
||||
*/
|
||||
private void flip() {
|
||||
int[] t = cost;
|
||||
cost = back;
|
||||
back = t;
|
||||
}
|
||||
|
||||
private int min(int a,int b,int c) {
|
||||
return Math.min(a,Math.min(b,c));
|
||||
}
|
||||
|
||||
private int calc() {
|
||||
for( int j=0; j<b.length(); j++ ) {
|
||||
flip();
|
||||
cost[0] = j+1;
|
||||
for( int i=0; i<a.length(); i++ ) {
|
||||
int match = (a.charAt(i)==b.charAt(j))?0:1;
|
||||
cost[i+1] = min( back[i]+match, cost[i]+1, back[i+1]+1 );
|
||||
}
|
||||
}
|
||||
return cost[a.length()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Maps an error to a fatal error.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class FatalAdapter implements ErrorHandler {
|
||||
private final ErrorHandler core;
|
||||
|
||||
public FatalAdapter(ErrorHandler handler) {
|
||||
this.core = handler;
|
||||
}
|
||||
|
||||
public void warning (SAXParseException exception) throws SAXException {
|
||||
core.warning(exception);
|
||||
}
|
||||
|
||||
public void error (SAXParseException exception) throws SAXException {
|
||||
core.fatalError(exception);
|
||||
}
|
||||
|
||||
public void fatalError (SAXParseException exception) throws SAXException {
|
||||
core.fatalError(exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* {@link Iterator} that walks over a map of maps.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class FlattenIterator<T> implements Iterator<T> {
|
||||
|
||||
private final Iterator<? extends Map<?,? extends T>> parent;
|
||||
private Iterator<? extends T> child = null;
|
||||
private T next;
|
||||
|
||||
public FlattenIterator( Iterable<? extends Map<?,? extends T>> core ) {
|
||||
this.parent = core.iterator();
|
||||
}
|
||||
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
getNext();
|
||||
return next!=null;
|
||||
}
|
||||
|
||||
public T next() {
|
||||
T r = next;
|
||||
next = null;
|
||||
if(r==null)
|
||||
throw new NoSuchElementException();
|
||||
return r;
|
||||
}
|
||||
|
||||
private void getNext() {
|
||||
if(next!=null) return;
|
||||
|
||||
if(child!=null && child.hasNext()) {
|
||||
next = child.next();
|
||||
return;
|
||||
}
|
||||
// child is empty
|
||||
if(parent.hasNext()) {
|
||||
child = parent.next().values().iterator();
|
||||
getNext();
|
||||
}
|
||||
// else
|
||||
// no more object
|
||||
}
|
||||
}
|
||||
480
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/QNameMap.java
Normal file
480
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/QNameMap.java
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.Name;
|
||||
|
||||
/**
|
||||
* Map keyed by {@link QName}.
|
||||
*
|
||||
* This specialized map allows a look up operation without constructing
|
||||
* a new QName instance, for a performance reason. This {@link Map} assumes
|
||||
* that both namespace URI and local name are {@link String#intern() intern}ed.
|
||||
*
|
||||
* @since JAXB 2.0
|
||||
*/
|
||||
public final class QNameMap<V> {
|
||||
/**
|
||||
* The default initial capacity - MUST be a power of two.
|
||||
*/
|
||||
private static final int DEFAULT_INITIAL_CAPACITY = 16;
|
||||
|
||||
/**
|
||||
* The maximum capacity, used if a higher value is implicitly specified
|
||||
* by either of the constructors with arguments.
|
||||
* MUST be a power of two <= 1<<30.
|
||||
*/
|
||||
private static final int MAXIMUM_CAPACITY = 1 << 30;
|
||||
|
||||
/**
|
||||
* The table, resized as necessary. Length MUST Always be a power of two.
|
||||
*/
|
||||
transient Entry<V>[] table = new Entry[DEFAULT_INITIAL_CAPACITY];
|
||||
|
||||
/**
|
||||
* The number of key-value mappings contained in this identity hash map.
|
||||
*/
|
||||
transient int size;
|
||||
|
||||
/**
|
||||
* The next size value at which to resize . Taking it as
|
||||
* MAXIMUM_CAPACITY
|
||||
* @serial
|
||||
*/
|
||||
private int threshold;
|
||||
|
||||
/**
|
||||
* The load factor used when none specified in constructor.
|
||||
**/
|
||||
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gives an entrySet view of this map
|
||||
*/
|
||||
private Set<Entry<V>> entrySet = null;
|
||||
|
||||
public QNameMap() {
|
||||
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
|
||||
table = new Entry[DEFAULT_INITIAL_CAPACITY];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the specified value with the specified keys in this map.
|
||||
* If the map previously contained a mapping for this key, the old
|
||||
* value is replaced.
|
||||
*
|
||||
* @param namespaceUri First key with which the specified value is to be associated.
|
||||
* @param localname Second key with which the specified value is to be associated.
|
||||
* @param value value to be associated with the specified key.
|
||||
*
|
||||
*/
|
||||
public void put(String namespaceUri,String localname, V value ) {
|
||||
//keys cannot be null
|
||||
assert localname !=null;
|
||||
assert namespaceUri !=null;
|
||||
// keys must be interned
|
||||
assert localname == localname.intern();
|
||||
assert namespaceUri == namespaceUri.intern();
|
||||
|
||||
int hash = hash(localname);
|
||||
int i = indexFor(hash, table.length);
|
||||
|
||||
for (Entry<V> e = table[i]; e != null; e = e.next) {
|
||||
if (e.hash == hash && localname == e.localName && namespaceUri==e.nsUri) {
|
||||
e.value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addEntry(hash, namespaceUri,localname, value, i);
|
||||
|
||||
}
|
||||
|
||||
public void put(QName name, V value ) {
|
||||
put(name.getNamespaceURI(),name.getLocalPart(),value);
|
||||
}
|
||||
|
||||
public void put(Name name, V value ) {
|
||||
put(name.nsUri,name.localName,value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified keys are mapped in this QNameMap,
|
||||
* or <tt>null</tt> if the map contains no mapping for this key.
|
||||
*
|
||||
* @param nsUri the namespaceUri key whose associated value is to be returned.
|
||||
* @param localPart the localPart key whose associated value is to be returned.
|
||||
* @return the value to which this map maps the specified set of keya, or
|
||||
* <tt>null</tt> if the map contains no mapping for this set of keys.
|
||||
* @see #put(String,String, Object)
|
||||
*/
|
||||
public V get( String nsUri, String localPart ) {
|
||||
Entry<V> e = getEntry(nsUri,localPart);
|
||||
if(e==null) return null;
|
||||
else return e.value;
|
||||
}
|
||||
|
||||
public V get( QName name ) {
|
||||
return get(name.getNamespaceURI(),name.getLocalPart());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of keys-value mappings in this map.
|
||||
*
|
||||
* @return the number of keys-value mappings in this map.
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all of the mappings from the specified map to this map
|
||||
* These mappings will replace any mappings that
|
||||
* this map had for any of the keys currently in the specified map.
|
||||
*
|
||||
* @param map mappings to be stored in this map.
|
||||
*
|
||||
*/
|
||||
public QNameMap<V> putAll(QNameMap<? extends V> map) {
|
||||
int numKeysToBeAdded = map.size();
|
||||
if (numKeysToBeAdded == 0)
|
||||
return this;
|
||||
|
||||
|
||||
if (numKeysToBeAdded > threshold) {
|
||||
int targetCapacity = numKeysToBeAdded;
|
||||
if (targetCapacity > MAXIMUM_CAPACITY)
|
||||
targetCapacity = MAXIMUM_CAPACITY;
|
||||
int newCapacity = table.length;
|
||||
while (newCapacity < targetCapacity)
|
||||
newCapacity <<= 1;
|
||||
if (newCapacity > table.length)
|
||||
resize(newCapacity);
|
||||
}
|
||||
|
||||
for( Entry<? extends V> e : map.entrySet() )
|
||||
put(e.nsUri,e.localName,e.getValue());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a hash value for the specified object.The hash value is computed
|
||||
* for the localName.
|
||||
*/
|
||||
private static int hash(String x) {
|
||||
int h = x.hashCode();
|
||||
|
||||
h += ~(h << 9);
|
||||
h ^= (h >>> 14);
|
||||
h += (h << 4);
|
||||
h ^= (h >>> 10);
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns index for hash code h.
|
||||
*/
|
||||
private static int indexFor(int h, int length) {
|
||||
return h & (length-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new entry with the specified keys, value and hash code to
|
||||
* the specified bucket. It is the responsibility of this
|
||||
* method to resize the table if appropriate.
|
||||
*
|
||||
*/
|
||||
private void addEntry(int hash, String nsUri, String localName, V value, int bucketIndex) {
|
||||
Entry<V> e = table[bucketIndex];
|
||||
table[bucketIndex] = new Entry<V>(hash, nsUri, localName, value, e);
|
||||
if (size++ >= threshold)
|
||||
resize(2 * table.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rehashes the contents of this map into a new array with a
|
||||
* larger capacity. This method is called automatically when the
|
||||
* number of keys in this map reaches its threshold.
|
||||
*/
|
||||
private void resize(int newCapacity) {
|
||||
Entry[] oldTable = table;
|
||||
int oldCapacity = oldTable.length;
|
||||
if (oldCapacity == MAXIMUM_CAPACITY) {
|
||||
threshold = Integer.MAX_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
Entry[] newTable = new Entry[newCapacity];
|
||||
transfer(newTable);
|
||||
table = newTable;
|
||||
threshold = newCapacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer all entries from current table to newTable.
|
||||
*/
|
||||
private void transfer(Entry<V>[] newTable) {
|
||||
Entry<V>[] src = table;
|
||||
int newCapacity = newTable.length;
|
||||
for (int j = 0; j < src.length; j++) {
|
||||
Entry<V> e = src[j];
|
||||
if (e != null) {
|
||||
src[j] = null;
|
||||
do {
|
||||
Entry<V> next = e.next;
|
||||
int i = indexFor(e.hash, newCapacity);
|
||||
e.next = newTable[i];
|
||||
newTable[i] = e;
|
||||
e = next;
|
||||
} while (e != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one random item in the map.
|
||||
* If this map is empty, return null.
|
||||
*
|
||||
* <p>
|
||||
* This method is useful to obtain the value from a map that only contains one element.
|
||||
*/
|
||||
public Entry<V> getOne() {
|
||||
for( Entry<V> e : table ) {
|
||||
if(e!=null)
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<QName> keySet() {
|
||||
Set<QName> r = new HashSet<QName>();
|
||||
for (Entry<V> e : entrySet()) {
|
||||
r.add(e.createQName());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private abstract class HashIterator<E> implements Iterator<E> {
|
||||
Entry<V> next; // next entry to return
|
||||
int index; // current slot
|
||||
|
||||
HashIterator() {
|
||||
Entry<V>[] t = table;
|
||||
int i = t.length;
|
||||
Entry<V> n = null;
|
||||
if (size != 0) { // advance to first entry
|
||||
while (i > 0 && (n = t[--i]) == null) {}
|
||||
}
|
||||
next = n;
|
||||
index = i;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
Entry<V> nextEntry() {
|
||||
Entry<V> e = next;
|
||||
if (e == null)
|
||||
throw new NoSuchElementException();
|
||||
|
||||
Entry<V> n = e.next;
|
||||
Entry<V>[] t = table;
|
||||
int i = index;
|
||||
while (n == null && i > 0)
|
||||
n = t[--i];
|
||||
index = i;
|
||||
next = n;
|
||||
return e;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(String nsUri,String localName) {
|
||||
return getEntry(nsUri,localName)!=null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this map is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
|
||||
public static final class Entry<V> {
|
||||
/** The namespace URI. */
|
||||
public final String nsUri;
|
||||
|
||||
/** The localPart. */
|
||||
public final String localName;
|
||||
|
||||
V value;
|
||||
final int hash;
|
||||
Entry<V> next;
|
||||
|
||||
/**
|
||||
* Create new entry.
|
||||
*/
|
||||
Entry(int h, String nsUri, String localName, V v, Entry<V> n) {
|
||||
value = v;
|
||||
next = n;
|
||||
this.nsUri = nsUri;
|
||||
this.localName = localName;
|
||||
hash = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new QName object from {@link #nsUri} and {@link #localName}.
|
||||
*/
|
||||
public QName createQName() {
|
||||
return new QName(nsUri,localName);
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public V setValue(V newValue) {
|
||||
V oldValue = value;
|
||||
value = newValue;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Entry))
|
||||
return false;
|
||||
Entry e = (Entry)o;
|
||||
String k1 = nsUri;
|
||||
String k2 = e.nsUri;
|
||||
String k3 = localName;
|
||||
String k4 = e.localName;
|
||||
if (k1 == k2 || (k1 != null && k1.equals(k2)) &&
|
||||
(k3 == k4 ||(k3 !=null && k3.equals(k4)))) {
|
||||
Object v1 = getValue();
|
||||
Object v2 = e.getValue();
|
||||
if (v1 == v2 || (v1 != null && v1.equals(v2)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ( localName.hashCode()) ^
|
||||
(value==null ? 0 : value.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return '"'+nsUri +"\",\"" +localName + "\"=" + getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Entry<V>> entrySet() {
|
||||
Set<Entry<V>> es = entrySet;
|
||||
return es != null ? es : (entrySet = new EntrySet());
|
||||
}
|
||||
|
||||
private Iterator<Entry<V>> newEntryIterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
private class EntryIterator extends HashIterator<Entry<V>> {
|
||||
public Entry<V> next() {
|
||||
return nextEntry();
|
||||
}
|
||||
}
|
||||
private class EntrySet extends AbstractSet<Entry<V>> {
|
||||
public Iterator<Entry<V>> iterator() {
|
||||
return newEntryIterator();
|
||||
}
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (!(o instanceof Entry))
|
||||
return false;
|
||||
Entry<V> e = (Entry<V>) o;
|
||||
Entry<V> candidate = getEntry(e.nsUri,e.localName);
|
||||
return candidate != null && candidate.equals(e);
|
||||
}
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
private Entry<V> getEntry(String nsUri,String localName) {
|
||||
// strings must be interned
|
||||
assert nsUri==nsUri.intern();
|
||||
assert localName==localName.intern();
|
||||
|
||||
int hash = hash(localName);
|
||||
int i = indexFor(hash, table.length);
|
||||
Entry<V> e = table[i];
|
||||
while (e != null && !(localName == e.localName && nsUri == e.nsUri))
|
||||
e = e.next;
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append('{');
|
||||
|
||||
for( Entry<V> e : entrySet() ) {
|
||||
if(buf.length()>1)
|
||||
buf.append(',');
|
||||
buf.append('[');
|
||||
buf.append(e);
|
||||
buf.append(']');
|
||||
}
|
||||
|
||||
buf.append('}');
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
/**
|
||||
* Created to record the caller stack trace in logging.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class StackRecorder extends Throwable {
|
||||
}
|
||||
48
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/TypeCast.java
Normal file
48
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/TypeCast.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class TypeCast {
|
||||
/**
|
||||
* Makes sure that a map contains the right type, and returns it to the desirable type.
|
||||
*/
|
||||
public static <K,V> Map<K,V> checkedCast( Map<?,?> m, Class<K> keyType, Class<V> valueType ) {
|
||||
if(m==null)
|
||||
return null;
|
||||
for (Map.Entry e : m.entrySet()) {
|
||||
if(!keyType.isInstance(e.getKey()))
|
||||
throw new ClassCastException(e.getKey().getClass().toString());
|
||||
if(!valueType.isInstance(e.getValue()))
|
||||
throw new ClassCastException(e.getValue().getClass().toString());
|
||||
}
|
||||
return (Map<K,V>)m;
|
||||
}
|
||||
}
|
||||
265
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/XmlFactory.java
Normal file
265
jdkSrc/jdk8/com/sun/xml/internal/bind/v2/util/XmlFactory.java
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.bind.v2.util;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.Messages;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import javax.xml.xpath.XPathFactoryConfigurationException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
|
||||
/**
|
||||
* Provides helper methods for creating properly configured XML parser
|
||||
* factory instances with namespace support turned on and configured for
|
||||
* security.
|
||||
* @author snajper
|
||||
*/
|
||||
public class XmlFactory {
|
||||
|
||||
// not in older JDK, so must be duplicated here, otherwise javax.xml.XMLConstants should be used
|
||||
public static final String ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema";
|
||||
public static final String ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD";
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(XmlFactory.class.getName());
|
||||
|
||||
/**
|
||||
* If true XML security features when parsing XML documents will be disabled.
|
||||
* The default value is false.
|
||||
*
|
||||
* Boolean
|
||||
* @since 2.2.6
|
||||
*/
|
||||
private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.bind.disableXmlSecurity";
|
||||
|
||||
private static final boolean XML_SECURITY_DISABLED = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return Boolean.getBoolean(DISABLE_XML_SECURITY);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
private static boolean isXMLSecurityDisabled(boolean runtimeSetting) {
|
||||
return XML_SECURITY_DISABLED || runtimeSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properly configured (e.g. security features) schema factory
|
||||
* - namespaceAware == true
|
||||
* - securityProcessing == is set based on security processing property, default is true
|
||||
*/
|
||||
public static SchemaFactory createSchemaFactory(final String language, boolean disableSecureProcessing) throws IllegalStateException {
|
||||
try {
|
||||
SchemaFactory factory = SchemaFactory.newInstance(language);
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "SchemaFactory instance: {0}", factory);
|
||||
}
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !isXMLSecurityDisabled(disableSecureProcessing));
|
||||
return factory;
|
||||
} catch (SAXNotRecognizedException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException(ex);
|
||||
} catch (SAXNotSupportedException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException(ex);
|
||||
} catch (AbstractMethodError er) {
|
||||
LOGGER.log(Level.SEVERE, null, er);
|
||||
throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properly configured (e.g. security features) parser factory
|
||||
* - namespaceAware == true
|
||||
* - securityProcessing == is set based on security processing property, default is true
|
||||
*/
|
||||
public static SAXParserFactory createParserFactory(boolean disableSecureProcessing) throws IllegalStateException {
|
||||
try {
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "SAXParserFactory instance: {0}", factory);
|
||||
}
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !isXMLSecurityDisabled(disableSecureProcessing));
|
||||
return factory;
|
||||
} catch (ParserConfigurationException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException( ex);
|
||||
} catch (SAXNotRecognizedException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException( ex);
|
||||
} catch (SAXNotSupportedException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException( ex);
|
||||
} catch (AbstractMethodError er) {
|
||||
LOGGER.log(Level.SEVERE, null, er);
|
||||
throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properly configured (e.g. security features) factory
|
||||
* - securityProcessing == is set based on security processing property, default is true
|
||||
*/
|
||||
public static XPathFactory createXPathFactory(boolean disableSecureProcessing) throws IllegalStateException {
|
||||
try {
|
||||
XPathFactory factory = XPathFactory.newInstance();
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "XPathFactory instance: {0}", factory);
|
||||
}
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !isXMLSecurityDisabled(disableSecureProcessing));
|
||||
return factory;
|
||||
} catch (XPathFactoryConfigurationException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException( ex);
|
||||
} catch (AbstractMethodError er) {
|
||||
LOGGER.log(Level.SEVERE, null, er);
|
||||
throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properly configured (e.g. security features) factory
|
||||
* - securityProcessing == is set based on security processing property, default is true
|
||||
*/
|
||||
public static TransformerFactory createTransformerFactory(boolean disableSecureProcessing) throws IllegalStateException {
|
||||
try {
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "TransformerFactory instance: {0}", factory);
|
||||
}
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !isXMLSecurityDisabled(disableSecureProcessing));
|
||||
return factory;
|
||||
} catch (TransformerConfigurationException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException( ex);
|
||||
} catch (AbstractMethodError er) {
|
||||
LOGGER.log(Level.SEVERE, null, er);
|
||||
throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properly configured (e.g. security features) factory
|
||||
* - namespaceAware == true
|
||||
* - securityProcessing == is set based on security processing property, default is true
|
||||
*/
|
||||
public static DocumentBuilderFactory createDocumentBuilderFactory(boolean disableSecureProcessing) throws IllegalStateException {
|
||||
try {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "DocumentBuilderFactory instance: {0}", factory);
|
||||
}
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !isXMLSecurityDisabled(disableSecureProcessing));
|
||||
return factory;
|
||||
} catch (ParserConfigurationException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
throw new IllegalStateException( ex);
|
||||
} catch (AbstractMethodError er) {
|
||||
LOGGER.log(Level.SEVERE, null, er);
|
||||
throw new IllegalStateException(Messages.INVALID_JAXP_IMPLEMENTATION.format(), er);
|
||||
}
|
||||
}
|
||||
|
||||
public static SchemaFactory allowExternalAccess(SchemaFactory sf, String value, boolean disableSecureProcessing) {
|
||||
|
||||
// if xml security (feature secure processing) disabled, nothing to do, no restrictions applied
|
||||
if (isXMLSecurityDisabled(disableSecureProcessing)) {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, Messages.JAXP_XML_SECURITY_DISABLED.format());
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
if (System.getProperty("javax.xml.accessExternalSchema") != null) {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, Messages.JAXP_EXTERNAL_ACCESS_CONFIGURED.format());
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
try {
|
||||
sf.setProperty(ACCESS_EXTERNAL_SCHEMA, value);
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, Messages.JAXP_SUPPORTED_PROPERTY.format(ACCESS_EXTERNAL_SCHEMA));
|
||||
}
|
||||
} catch (SAXException ignored) {
|
||||
// nothing to do; support depends on version JDK or SAX implementation
|
||||
if (LOGGER.isLoggable(Level.CONFIG)) {
|
||||
LOGGER.log(Level.CONFIG, Messages.JAXP_UNSUPPORTED_PROPERTY.format(ACCESS_EXTERNAL_SCHEMA), ignored);
|
||||
}
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
public static SchemaFactory allowExternalDTDAccess(SchemaFactory sf, String value, boolean disableSecureProcessing) {
|
||||
|
||||
// if xml security (feature secure processing) disabled, nothing to do, no restrictions applied
|
||||
if (isXMLSecurityDisabled(disableSecureProcessing)) {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, Messages.JAXP_XML_SECURITY_DISABLED.format());
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
if (System.getProperty("javax.xml.accessExternalDTD") != null) {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, Messages.JAXP_EXTERNAL_ACCESS_CONFIGURED.format());
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
try {
|
||||
sf.setProperty(ACCESS_EXTERNAL_DTD, value);
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, Messages.JAXP_SUPPORTED_PROPERTY.format(ACCESS_EXTERNAL_DTD));
|
||||
}
|
||||
} catch (SAXException ignored) {
|
||||
// nothing to do; support depends on version JDK or SAX implementation
|
||||
if (LOGGER.isLoggable(Level.CONFIG)) {
|
||||
LOGGER.log(Level.CONFIG, Messages.JAXP_UNSUPPORTED_PROPERTY.format(ACCESS_EXTERNAL_DTD), ignored);
|
||||
}
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user