http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java new file mode 100644 index 0000000..4a048bb --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java @@ -0,0 +1,80 @@ +/* + * 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.jena.iri.impl; + + +import org.apache.jena.iri.IRI ; +import org.apache.jena.iri.IRIException ; +import org.apache.jena.iri.IRIFactoryI ; + +abstract public class AbsIRIFactoryImpl implements IRIFactoryI { + + protected abstract IRIFactoryImpl getFactory(); + public AbsIRIFactoryImpl() { + } + +// public IRI create(String s) { +// return create(s); +// } + + @Override + public IRI create(String s) { + return create(new IRIImpl(getFactory(),s ) +// , +// throwEx?AbsIRIImpl.ALL_EXCEPTIONS: +// AbsIRIImpl.NO_EXCEPTIONS) + ); + } + + //@Override + @Override + public IRI construct(String s) throws IRIException { + return throwAnyErrors(create(s)); + } + + //@Override + @Override + public IRI construct(IRI i) throws IRIException { + return throwAnyErrors(create(i)); + +// +// try { +// return create(i,true); +// } catch (Violation e) { +// throw new IRIImplException(e); +// } + } + protected IRI throwAnyErrors(IRI rslt) throws IRIException { + if (rslt.hasViolation(false)) { + throw new IRIImplException(rslt.violations(false).next()); +// Iterator it = rslt.exceptions(); +// while (it.hasNext()){ +// Violation v = (Violation)it.next(); +// if (v.isError()) +// throw new IRIImplException(v); +// } + } + return rslt; + } +// public IRI create(IRI i) { +// return create(i); +// } + @Override + abstract public IRI create(IRI i); +}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java new file mode 100644 index 0000000..fec96ef --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java @@ -0,0 +1,787 @@ +/* + * 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.jena.iri.impl; + +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import java.net.IDN; + +import org.apache.jena.iri.* ; +/* +import com.vgrs.xcode.idna.Idna; +import com.vgrs.xcode.idna.Nameprep; +import com.vgrs.xcode.idna.Punycode; +import com.vgrs.xcode.util.XcodeException; +*/ +abstract public class AbsIRIImpl extends IRI implements + ViolationCodes, IRIComponents { + + private static final int defaultRelative = ABSOLUTE | SAMEDOCUMENT | CHILD + | PARENT | GRANDPARENT; + + static String removeDotSegments(String path) { + // 5.2.4 step 1. + int inputBufferStart = 0; + int inputBufferEnd = path.length(); + StringBuffer output = new StringBuffer(); + // 5.2.4 step 2. + while (inputBufferStart < inputBufferEnd) { + String in = path.substring(inputBufferStart); + // 5.2.4 step 2A + if (in.startsWith("./")) { + inputBufferStart += 2; + continue; + } + if (in.startsWith("../")) { + inputBufferStart += 3; + continue; + } + // 5.2.4 2 B. + if (in.startsWith("/./")) { + inputBufferStart += 2; + continue; + } + if (in.equals("/.")) { + in = "/"; // don't continue, process below. + inputBufferStart += 2; // force end of loop + } + // 5.2.4 2 C. + if (in.startsWith("/../")) { + inputBufferStart += 3; + removeLastSeqment(output); + continue; + } + if (in.equals("/..")) { + in = "/"; // don't continue, process below. + inputBufferStart += 3; // force end of loop + removeLastSeqment(output); + } + // 5.2.4 2 D. + if (in.equals(".")) { + inputBufferStart += 1; + continue; + } + if (in.equals("..")) { + inputBufferStart += 2; + continue; + } + // 5.2.4 2 E. + int nextSlash = in.indexOf('/', 1); + if (nextSlash == -1) + nextSlash = in.length(); + inputBufferStart += nextSlash; + output.append(in.substring(0, nextSlash)); + } + // 5.2.4 3 + return output.toString(); + } + + private static void removeLastSeqment(StringBuffer output) { + int ix = output.length(); + while (ix > 0) { + ix--; + if (output.charAt(ix) == '/') + break; + } + output.setLength(ix); + } + + private long foundExceptionMask; + + long allErrors; + + abstract long errors(int field); + + abstract SchemeSpecificPart getSchemeSpec(); + abstract Exception getIDNAException(); + + // void throwExceptions(IRIFactoryImpl f, boolean includeRelative) { + // long mask = f.exceptions; + // if (!includeRelative) + // mask &= ~(1l << RELATIVE_URI); + // if (hasExceptionMask(mask)) { + // throw (IRIImplUncheckedException) exceptionsMask(mask).next(); + // } + // } + + boolean hasExceptionMask(long mask) { + return (allErrors & mask) != 0; + } + + private ArrayList<Violation> foundExceptions; + + protected String path; +/* + static private Idna idna; + static { + try { + idna = new Idna(new Punycode(), new Nameprep()); + } catch (XcodeException e) { + System.err.println("Internal error in IDN setup"); + e.printStackTrace(); + } + } +*/ + static final private char hex[] = "0123456789ABCDEF".toCharArray(); + + static final Iterator<Violation> nullIterator = new ArrayList<Violation>(0).iterator(); + + protected static final int NO_EXCEPTIONS = 1; + + protected static final int ALL_EXCEPTIONS = 2; + + protected static final int NOT_RELATIVE_EXCEPTIONS = 3; + + protected static final int PATH_INDEX = Parser.invFields[PATH]; + + public AbsIRIImpl() { + super(); + } + + Iterator<Violation> exceptionsMask(final long mask) { + createExceptions(mask); + return foundExceptions == null ? nullIterator : + new Iterator<Violation>() { + private Iterator<Violation> underlying = foundExceptions.iterator(); + + private Violation next; + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasNext() { + if (next==null) { + while (underlying.hasNext()) { + next = underlying.next(); + if (((1l << (next).getViolationCode()) + & mask) != 0) + return true; + } + next = null; + return false; + } + return true; + } + + @Override + public Violation next() { + if (hasNext()) { + Violation rslt = next; + next = null; + return rslt; + } + throw new NoSuchElementException(); + } + + }; + } + + private void createExceptions(long m) { + m &= ~foundExceptionMask; + if ((allErrors & m) != 0) { + if (foundExceptions == null) { + foundExceptions = new ArrayList<>(); + } + for (int i = 0; i < Parser.fields.length; i++) { + int f = Parser.fields[i]; + if ((errors(f) & m) != 0) { + for (int e = 0; e < 64; e++) + if (((1l << e) & m & errors(f)) != 0) { + foundExceptions.add(new ViolationImpl(this, f, e)); + } + + } + } + + } + foundExceptionMask |= m; + } + + @Override + public boolean isAbsolute() { + return has(SCHEME); + } + + abstract boolean has(int component); + + @Override + public boolean isRelative() { + return !has(SCHEME); + } + + /* + * public boolean isRDFURIReference() { return !hasException(RDF); } + * + * public boolean isIRI() { return !hasException(IRI); } + * + * public boolean isURIinASCII() { return !hasException(URI); } + */ + // public boolean isVeryBad() { + // return false; + // } + // public boolean isXSanyURI() { + // return !hasException(XMLSchema); + // } + /* + public boolean hasException(int conformance) { + return hasExceptionMask(getFactory().recsToMask(conformance)); + } + + public Iterator exceptions(int conformance) { + return exceptionsMask(getFactory().recsToMask(conformance)); + } + */ + + @Override + public boolean hasViolation(boolean includeWarnings) { + return hasExceptionMask(getSchemeSpec().getMask(includeWarnings)); + } + + @Override + public Iterator<Violation> violations(boolean includeWarnings) { + return exceptionsMask(getSchemeSpec().getMask(includeWarnings)); + } + + @Override + public URL toURL() throws MalformedURLException { + return new URL(toASCIIString()); + } + + // TODO ToAsciiMask + static long ToAsciiMask = + ~0l; + /* + (1l << LTR_CHAR) | (1l << ILLEGAL_CHAR) + | (1l << IRI_CHAR) | (1l << UNWISE_CHAR) | (1l << WHITESPACE) + | (1l << NOT_XML_SCHEMA_WHITESPACE) | (1l << NON_XML_CHARACTER) + | (1l << DOUBLE_DASH_IN_REG_NAME); +*/ + @Override + public String toASCIIString() throws MalformedURLException { + if (hasExceptionMask(ToAsciiMask)) { + return createASCIIString(); + } + return toString(); + } + + private String createASCIIString() throws MalformedURLException { + StringBuffer asciiString = new StringBuffer(); + + if (has(SCHEME)) { + toAscii(asciiString, getScheme(), errors(SCHEME)); + asciiString.append(':'); + } + if (has(AUTHORITY)) { + asciiString.append("//"); + if (has(USER)) { + toAscii(asciiString, getRawUserinfo(), errors(USER)); + asciiString.append('@'); + } + + String host = getRawHost(); + regNameToAscii(asciiString,host); + if (has(PORT)) { + asciiString.append(':'); + toAscii(asciiString, get(PORT), errors(USER)); + } + } + toAscii(asciiString, getRawPath(), errors(PATH)); + if (has(QUERY)) { + asciiString.append('?'); + toAscii(asciiString, getRawQuery(), errors(QUERY)); + } + if (has(FRAGMENT)) { + asciiString.append('#'); + toAscii(asciiString, getRawFragment(), errors(FRAGMENT)); + } + return asciiString.toString(); + } + + private void regNameToAscii(StringBuffer asciiString, String host) + throws MalformedURLException { + if ((errors(HOST) & ToAsciiMask) == 0) { + asciiString.append(host); + return; + } + + asciiString.append(domainToAscii(host)); + + } + + static CharSequence domainToAscii(String host) throws MalformedIDNException { + + try { + return IDNP.toASCII(host, IDN.USE_STD3_ASCII_RULES|IDN.ALLOW_UNASSIGNED); + } catch (Exception e) { + throw new MalformedIDNException(e); + } + /* + int u[] = new int[host.length()]; + for (int i = 0; i < host.length(); i++) + u[i] = host.charAt(i); + + try { + return idna.domainToAscii(u); + } catch (XcodeException e) { + throw new MalformedIDNException(e); + } + */ + } + + private void toAscii(StringBuffer asciiString, String field, long errs) { + if ((errs & ToAsciiMask) == 0) { + asciiString.append(field); + return; + } + // 3.1 RFC 3987 + // Step 1c + + // nothing + + // Step 2a + /* + * Step 2. For each character in 'ucschar' or 'iprivate', apply steps + * 2.1 through 2.3 below. + * + * We interpret this as any charcater above 127, below 32 and the unwise + * chars + * + * Systems accepting IRIs MAY also deal with the printable characters in + * US-ASCII that are not allowed in URIs, namely "<", ">", '"', space, + * "{", "}", "|", "\", "^", and "`", in step 2 above. + */ + for (int i = 0; i < field.length(); i++) { + // TODO Java 1.4/1.5 issue + int ch = field.charAt(i); + if (ch > 127 || "<>\" {}|\\^`".indexOf(ch) != -1 || ch < 32) { + // 2.1 + byte b[]; + try { + b = field.substring(i, i + 1).getBytes("utf-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Impossible - utf-8 unsupported"); + } + // 2.2, 2.3 + for ( byte aB : b ) + { + char buf[] = { '%', hex[( aB & ( 255 & ~15 ) ) >> 4], hex[aB & 15] }; + + asciiString.append( buf ); + } + } else { + asciiString.append(new char[] { (char) ch }); + } + } + } + +/* + * Subroutine for relativize. + * + * Relativizing path components is somewhat tricky. + * The code is in the method PathRelative.check + * which is invoked from relativizePaths + * + * There are only three static stateless objects of this class, + * each of which checks for a particular rule. + * + * The child object behaves slightly differently, + * with a helper method overridden, and one line of + * code specific to that object only. + * + */ + + static private final PathRelativize + child = new PathRelativize(CHILD, CHILD | PARENT | GRANDPARENT, + "."){ + @Override + String descendentMatch(String descendent) { + return maybeDotSlash( descendent); + } + }, + parent = new PathRelativize(PARENT, PARENT | GRANDPARENT, + ".."), + grandparent = new PathRelativize(GRANDPARENT, GRANDPARENT, + "../.."); + + /** + * + * @param in The path from this IRI + * @param out If successful, out[0] contains the answer + * @param flags Currently applicable rules + * @param rel The path to make relative + * @return True if the paths were relativized. + */ + private boolean relativizePaths(String in, String[] out, int flags, String rel) { + if (child.check(in, out, flags, rel)) + return true; + if (parent.check(out[0], out, flags, rel)) + return true; + return grandparent.check(out[0], out, flags, rel); + } + + static class PathRelativize { + final private int flag; + final private int allFlags; + final private String replacement; + /** + * + * @param flag If this flag is not present then this rule does not apply. + * @param allFlags If none of these flags are present then this rule and subsequence rules do not apply. + * @param replacement If there is a match, then use this as the relative path + */ + PathRelativize(int flag, int allFlags, String replacement) { + this.flag = flag; + this.replacement = replacement; + this.allFlags = allFlags; + } + /** + * Return true if the rule applied. + * The result of the rule is returned in out[0] + * Return false if the rule did not apply. + * The input for the next rule is in out[0] + * @param in Absolute path to use in match + * @param out Result, as above. + * @param flags controlling rule applicability + * @param rel Relative path to use in match + * @return + */ + boolean check(String in, String out[], int flags, String rel) { + out[0] = null; + if (in==null) + return false; + if ((flags & allFlags) == 0) + return false; + int ix = in.lastIndexOf('/'); + if (ix==-1) + return false; + if (ix==0 && (flags & ABSOLUTE)!=0 && flag != CHILD) + return false; + in = in.substring(0,ix+1); + out[0] = in.substring(0,ix); + if ((flags & flag) == 0) + return false; + if (!rel.startsWith(in)) + return false; + if (rel.length() == ix+1) { + out[0] = replacement; + return true; + } + out[0] = descendentMatch(rel.substring(ix+1)); + return true; + } + + String descendentMatch(String descendent) { + return replacement + "/" + descendent; + } + + } + + + @Override + public IRI relativize(String abs, int flags) { + return relativize(new IRIImpl(getFactory(), abs), flags); + } + + @Override + public IRI relativize(String abs) { + return relativize(abs, defaultRelative); + } + + @Override + public IRI relativize(IRI abs) { + return relativize(abs, defaultRelative); + } + /* + * public String relativize(String abs, int flags) { return + * relativize(factory.create(abs),abs,flags); } + */ + @Override + public IRI relativize(IRI abs, int flags) { + String rslt = relativize(abs, null, flags); + return rslt == null ? abs : getFactory().create(rslt); + } + /** + * + * @param r + * @param def + * Default result if can't make this relative. + * @param flags + */ + private String relativize(IRI r, String def, int flags) { + if (!has(AUTHORITY)) // we could use the new rules for relative URIs for rootless, but I don't like them + return def; + if (!((AbsIRIImpl)r).has(AUTHORITY)) + return def; + // logger.info("<"+Util.substituteStandardEntities(abs)+">"); + // logger.info("<"+Util.substituteStandardEntities(r.m_path)+">"); + boolean net = equal(r.getScheme(), getScheme()); + boolean absl = net && equal(r.getRawHost(), getRawHost()) + && equal(getRawUserinfo(), r.getRawUserinfo()) + && equal(getPort(), r.getPort()); + boolean same = absl && equal(getRawPath(), r.getRawPath()) + && equal(getRawQuery(), r.getRawQuery()); + + String rslt = r.getRawFragment() == null ? "" : ("#" + r + .getRawFragment()); + + if (same && (flags & SAMEDOCUMENT) != 0) + return rslt; + + String thisPath = getRawPath(); + String pathToRel = r.getRawPath(); + if (r.getRawQuery() != null) { + rslt = "?" + r.getRawQuery() + rslt; + if (equal(thisPath,pathToRel) + && (flags & CHILD)!=0 ) { + return rslt; + } + } + if (absl) { + if (pathToRel.length()>0) { + if (thisPath.length()>0) { + String out[] = new String[]{null}; + if (relativizePaths(thisPath, out, flags, pathToRel)) { + return out[0]+rslt; + } + } + rslt = r.getRawPath() + rslt; + if (absl && (flags & ABSOLUTE) != 0) { + return rslt; + } + } + } else + rslt = r.getRawPath() + rslt; + if (net && (flags & NETWORK) != 0) { + return "//" + + (r.getRawUserinfo() == null ? "" + : (r.getRawUserinfo() + "@")) + r.getRawHost() + + (r.getPort() == IRI.NO_PORT ? "" : (":" + ((AbsIRIImpl)r).get(PORT))) + rslt; + + } + return def; + } + + + static private String maybeDotSlash(String path) { + int colon = path.indexOf(':'); + if (colon == -1) + return path; + int slash = path.indexOf('/'); + if (slash==-1 || slash>colon) + return "./"+path; + return path; + } + + static private String getLastSlash(String s) { + int ix = s.lastIndexOf('/', s.length() - 2); + return s.substring(0, ix + 1); + } + + private boolean equal(String s1, String s2) { + return s1 == null ? s2 == null : s1.equals(s2); + } + + private boolean equal(int s1, int s2) { + return s1 == s2; + } + + public Iterator<Violation> allViolations() { + return exceptionsMask(~0l); + } + + @Override + public String getRawUserinfo() { + return get(USER); + } + + @Override + public int getPort() { + String port = get(PORT); + if (port == null) + return IRI.NO_PORT; + try { + int v = Integer.parseInt(port); + if (v<0) + return IRI.ILLFORMED_PORT; + return v; + } catch (Exception e) { + return IRI.ILLFORMED_PORT; + } + } + + @Override + public String getRawQuery() { + return get(QUERY); + } + + @Override + public String getRawFragment() { + return get(FRAGMENT); + } + + @Override + public String getRawHost() { + return get(HOST); + } + + @Override + public String getScheme() { + return get(SCHEME); + } + + abstract String get(int comp); + + @Override + public String getRawPath() { + return path; + } + + @Override + public boolean isRootless() { + if (!has(SCHEME)) + return false; + if (has(AUTHORITY)) + return false; + if (path.equals("")) + return false; + if (path.charAt(0) == '/') + return false; + return true; + } + + abstract String pathRemoveDots(); + + abstract boolean dotsOK(); + + @Override + public String getRawAuthority() { + return get(AUTHORITY); + } + + @Override + public IRI create(IRI i) { + return new ResolvedRelativeIRI(this, (AbsIRIImpl) getFactory() + .create(i)); + } + + @Override + public IRI create(String s) { + return create(new IRIImpl(getFactory(), s) ); + } + + @Override + public boolean equals(Object o) { + if (o == null) + return false; + if (!(o instanceof IRI)) + return false; + return toString().equals(o.toString()); + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + @Override + public String getAuthority() { + return getCooked(AUTHORITY); + } + + @Override + public String getFragment() { + return getCooked(FRAGMENT); + } + + @Override + public String getHost() { + return getCooked(HOST); + } + + @Override + public String getPath() { + return getCooked(PATH); + } + + @Override + public String getQuery() { + return getCooked(QUERY); + } + + @Override + public String getUserinfo() { + return getCooked(USER); + } + + private String getCooked(int component) { + // TODO getCooked + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public IRI normalize(boolean useDns) { + // TODO normalize + throw new UnsupportedOperationException("not yet implemented"); + } + + /* + * Bidirectional IRIs MUST be rendered in the same way as they would be if + * they were in a left-to-right embedding; i.e., as if they were preceded by + * U+202A, LEFT-TO-RIGHT EMBEDDING (LRE), and followed by U+202C, POP + * DIRECTIONAL FORMATTING (PDF). + * + */ + @Override + public String toDisplayString() { + return "\u202A" + toString() + "\u202C"; + } + + // TODO http://example.com/𐌀𐌁𐌂 => + // http://example.com/%F0%90%8C%80%F0%90%8C%81%F0%90%8C%82 + + @Override + public String getASCIIHost() throws MalformedURLException { + StringBuffer asciiString = new StringBuffer(); + + String host = getRawHost(); + if (host==null) + return null; + regNameToAscii(asciiString,host); + return asciiString.toString(); + } + + @Override + public boolean ladderEquals(IRI iri, int other) { + // TODO ladderEquals + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public int ladderEquals(IRI iri) { + // TODO ladderEquals + throw new UnsupportedOperationException("not yet implemented"); + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java new file mode 100644 index 0000000..ae08392 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java @@ -0,0 +1,255 @@ +/* + * 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.jena.iri.impl; + +import java.text.Normalizer ; +import java.lang.Character.UnicodeBlock ; + +import org.apache.jena.iri.ViolationCodes ; + +abstract class AbsLexer implements ViolationCodes { + + /* user code: */ + protected Parser parser; + protected int range; + + /* + yyreset(null); + this.zzAtEOF = true; + int length = parser.end(range)-parser.start(range); + zzEndRead = length; + while (length > zzBuffer.length) + zzBuffer = new char[zzBuffer.length*2]; + + */ + synchronized public void analyse(Parser p,int r) { + parser = p; + range = r; + if (!parser.has(range)) + return; + parser.uri.getChars( + parser.start(range), + parser.end(range), + zzBuffer(), + 0); + try { + yylex(); + } + catch (java.io.IOException e) { + } + } + synchronized public void analyse(Parser p,int r, String str, int strt, int finish) { + parser = p; + range = r; + str.getChars( + strt, + finish, + zzBuffer(), + 0); + try { + yylex(); + } + catch (java.io.IOException e) { + } + } + + + abstract int yylex() throws java.io.IOException; + abstract char[] zzBuffer(); + + protected void error(int e) { + parser.recordError(range,e); + } + + final protected void rule(int rule) { + parser.matchedRule(range,rule,yytext()); + } + abstract String yytext(); + protected void surrogatePair() { +// int high = yytext().charAt(0); +// int low = yytext().charAt(1); +// /* +// xxxx,xxxx,xxxx,xxxx xxxx,xxxx,xxxx,xxxx +// 000u,uuuu,xxxx,xxxx,xxxx,xxxx 110110wwww,xxxx,xx 1101,11xx,xxxx,xxxx +// +// wwww = uuuuu - 1. +// */ +// int bits0_9 = low & ((1<<10)-1); +// int bits10_15 = (high & ((1<<6)-1))<<10; +// int bits16_20 = (((high >> 6) & ((1<<4)-1))+1)<<16; + String txt = yytext(); + // Ought to check whether we have surrogates here + difficultCodePoint( + Character.toCodePoint(txt.charAt(0), txt.charAt(1)), + txt); + } + + private void difficultCodePoint(int codePoint, String txt) { + /* Legal XML + #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + */ + error(NON_URI_CHARACTER); + if (codePoint> 0xD7FF && codePoint < 0xE000) + error(NON_XML_CHARACTER); + if (codePoint>0xFFFD && codePoint < 0x10000) + error(NON_XML_CHARACTER); + + /* Discouraged XML chars + [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF], + [#1FFFE-#x1FFFF], [#2FFFE-#x2FFFF], [#3FFFE-#x3FFFF], + [#4FFFE-#x4FFFF], [#5FFFE-#x5FFFF], [#6FFFE-#x6FFFF], + [#7FFFE-#x7FFFF], [#8FFFE-#x8FFFF], [#9FFFE-#x9FFFF], + [#AFFFE-#xAFFFF], [#BFFFE-#xBFFFF], [#CFFFE-#xCFFFF], + [#DFFFE-#xDFFFF], [#EFFFE-#xEFFFF], [#FFFFE-#xFFFFF], + [#10FFFE-#x10FFFF]. + */ + + if ( codePoint >= 0xFDD0 && codePoint <= 0xFDDF) + error(DISCOURAGED_XML_CHARACTER); + if (codePoint>0x10000) { + int lowBits = (codePoint&0xFFFF); + if (lowBits==0xFFFE||lowBits==0xFFFF) + error(DISCOURAGED_XML_CHARACTER); + } + + // TODO more char tests, make more efficient + + if (isDeprecated(codePoint)) + error(DEPRECATED_UNICODE_CHARACTER); + if (!Character.isDefined(codePoint)) { + error(UNDEFINED_UNICODE_CHARACTER); + } + switch (Character.getType(codePoint)) { + case Character.PRIVATE_USE: + error(PRIVATE_USE_CHARACTER); + break; + case Character.CONTROL: + error(UNICODE_CONTROL_CHARACTER); + break; + case Character.UNASSIGNED: + error(UNASSIGNED_UNICODE_CHARACTER); + break; + } + + if (!Normalizer.isNormalized(txt, Normalizer.Form.NFC)) { + error(NOT_NFC); + } + + if (!Normalizer.isNormalized(txt, Normalizer.Form.NFKC)) { + error(NOT_NFKC); + } + + if (Character.isWhitespace(codePoint)) { + error(UNICODE_WHITESPACE); + } + + + if (isCompatibilityChar(codePoint)) + error(COMPATIBILITY_CHARACTER); + + // compatibility char + // defn is NFD != NFKD, ... hmmm + + } + + private boolean isCompatibilityChar(int codePoint) { + + // Slight optimistation inherited from ICU4J version + // Not sure it's worth it since we can't do some of the ICU4J checks + UnicodeBlock block = UnicodeBlock.of(codePoint); + + if (block == UnicodeBlock.CJK_COMPATIBILITY) { + /*(U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, + U+FA23, U+FA24, U+FA27, U+FA28, and U+FA29) + */ + switch (codePoint) { + case 0xFA0E: + case 0xFA0F: + case 0xFA11: + case 0xFA13: + case 0xFA14: + case 0xFA1F: + case 0xFA21: + case 0xFA23: + case 0xFA24: + case 0xFA27: + case 0xFA28: + case 0xFA29: + return false; + default: + return true; + } + } else if (block == UnicodeBlock.CJK_COMPATIBILITY_FORMS + || block == UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT + || block == UnicodeBlock.CJK_RADICALS_SUPPLEMENT + || block == UnicodeBlock.KANGXI_RADICALS + || block == UnicodeBlock.HANGUL_COMPATIBILITY_JAMO) { + return true; + } + + // codepoint -> charsequence ought to be easy + String cp = new String(new int[]{codePoint}, 0, 1); + + // Compatibility char is where NFD differs from NFKD + return + !Normalizer.normalize(cp,Normalizer.Form.NFD).equals( + Normalizer.normalize(cp,Normalizer.Form.NFKD) + ); + + } + + protected void difficultChar() { + difficultCodePoint(yytext().charAt(0),yytext()); + } + + /** + * Unicode deprecated characters. Not available from standard java libs. + * Taken from {@link "http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B:deprecated:%5D"} + * @param codePoint + * @return + */ + private static boolean isDeprecated(int codePoint) { + + // Common case + if (codePoint < 0x0149) return false; + + if (codePoint >= 0xE0020 && codePoint <= 0xE007F) return true; + + switch (codePoint) { + case 0x0149: + case 0x0673: + case 0x0F77: + case 0x0F79: + case 0x17A3: + case 0x17A4: + case 0x206A: + case 0x206B: + case 0x206C: + case 0x206D: + case 0x206E: + case 0x206F: + case 0x2329: + case 0x232A: + case 0xE0001: + return true; + default: + return false; + } + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java new file mode 100644 index 0000000..27999bf --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java @@ -0,0 +1,42 @@ +/* + * 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.jena.iri.impl; + +import java.io.File; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +public class BuildViolationCodes { + public static void main(String[] args) throws TransformerException, TransformerFactoryConfigurationError { + Transformer xsl = + TransformerFactory.newInstance().newTransformer( + new StreamSource(new File("src/main/xml/org/apache/jena/iri/impl/viol2java.xsl")) + ); + xsl.transform( + new StreamSource(new File("src/main/xml/org/apache/jena/iri/impl/violations.xml")), + new StreamResult(new File("src/main/java/org/apache/jena/iri/ViolationCodes.java")) + + ); + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java new file mode 100644 index 0000000..fad1559 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java @@ -0,0 +1,58 @@ +/* + * 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.jena.iri.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.jena.iri.ViolationCodes ; + + +public class ComponentPattern implements ViolationCodes { + final Pattern pattern; + + final GroupAction actions[]; + + static final List<Pattern> allPatterns = new ArrayList<>(); + + ComponentPattern(String p) { + ComponentPatternParser parser = new ComponentPatternParser(p); + pattern = parser.get(); + actions = parser.actions(); +// System.err.println(allPatterns.size() + ": " + p + " ==> " +// + pattern.toString()); + allPatterns.add(pattern); + } + + + + public void analyse(Parser parser, int range) { + Matcher m = pattern.matcher(parser.get(range)); + if (!m.matches()) { + parser.recordError(range, SCHEME_PATTERN_MATCH_FAILED); + return; + } + for (int g = 1; g <= m.groupCount(); g++) + if (m.start(g) != -1) + actions[g].check(m, parser, range); + + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java new file mode 100644 index 0000000..b510893 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java @@ -0,0 +1,323 @@ +/* + * 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.jena.iri.impl; + +import java.util.List; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.jena.iri.ViolationCodes ; + + +public class ComponentPatternParser implements ViolationCodes { + static String separators = "([(](?![?]))|([(][?])|([)])|(\\[)|(\\])|([@][{])|([}]|[a-z]-[a-z])"; + + static final int OPEN_PAREN = 1; + + static final int OPEN_NON_CAPTURING_PAREN = 2; + + static final int CLOSE_PAREN = 3; + + static final int OPEN_SQ = 4; + + static final int CLOSE_SQ = 5; + + static final int OPEN_VAR = 6; + + static final int CLOSE_BRACE = 7; + + static final int LOWER_CASE_RANGE = 8; + + static final int OTHER = -1; + + static final Pattern keyword = Pattern.compile(separators); + + /* .NET port does not like this. Reworked. + * + static final Pattern splitter = Pattern.compile("(?=" + separators + + ")|(?<=" + separators + ")"); + + + public ComponentPatternParser(String p) { + split = splitter.split(p); + field = 0; + classify = new int[split.length]; + for (int i = 0; i < split.length; i++) + classify[i] = classify(split[i]); + while (field < split.length) + next(); +// System.err.println(p + " ==> "+ rslt.toString()); + pattern = Pattern.compile(rslt.toString()); + } +*/ + // working data + final String split[]; + + final int classify[]; + + int field; + + int groupCount; + + // result data + final StringBuffer rslt = new StringBuffer(); + + int shouldLowerCase; + + int mustLowerCase; + + int hostNames; + + final Pattern pattern; + + static final String emptyStringArray[] = new String[0]; + + static private String[] mySplit(String p) { + //return splitter.split(p); + + Matcher m = keyword.matcher(p); + List<String> rslt = new ArrayList<>(); + int pos = 0; +// rslt.add(""); + while (m.find()) { + if (m.start()>pos || pos==0) { + rslt.add(p.substring(pos,m.start())); + } + rslt.add(p.substring(m.start(),m.end())); + pos = m.end(); + } + if (pos < p.length()) + rslt.add(p.substring(pos)); + +// m. +// String preSplit[] = keyword.split(p); +// String rslt[] = new String[preSplit.length*2]; + + return rslt.toArray(emptyStringArray); + + } + +// static private String[] mySplitx(String p) { +// String r[] = mySplit(p); +// String s[] = splitter.split(p); +// if (r.length!=s.length) { +// System.err.println("Bad lengths: "+p+","+r.length+","+s.length); +// } +// for (int i=0;i<r.length && i <s.length;i++) +// if (!r[i].equals(s[i])) +// System.err.println("Bad component: "+p+","+r[i]+","+s[i]); +// return r; +// +// +// } + // end result data + public ComponentPatternParser(String p) { + split = mySplit(p); + field = 0; + classify = new int[split.length]; + for (int i = 0; i < split.length; i++) + classify[i] = classify(split[i]); + while (field < split.length) + next(); +// System.err.println(p + " ==> "+ rslt.toString()); + pattern = Pattern.compile(rslt.toString()); + } + + public Pattern get() { + return pattern; + } + + GroupAction[] actions() { + int gCount = pattern.matcher("").groupCount()+1; + GroupAction result[] = new GroupAction[gCount]; + for (int i=1;i<gCount;i++) { + int g = 1<<i; + if ((mustLowerCase & g)!=0) + result[i] = new ErrorAction(SCHEME_REQUIRES_LOWERCASE); + else if ((shouldLowerCase & g)!=0) + result[i] = new ErrorAction(SCHEME_PREFERS_LOWERCASE); + else if ((hostNames & g)!=0) + result[i] = new HostAction(i); + else + result[i] = GroupAction.NoAction; + } + return result; + } + + private int classify(String string) { + Matcher m = keyword.matcher(string); + if (!m.matches()) + return OTHER; + for (int i = 1; i <= m.groupCount(); i++) + if (m.start(i) != -1) + return i; + throw new IllegalStateException( + "IRI code internal error: no group matched."); + } + + private void untilCloseSq() { + while (classify[field - 1] != CLOSE_SQ) { + if (field >= split.length) + throw new IllegalArgumentException( + "Internal IRI code error. Did not find CLOSE_SQ in until()."); + add(); + } + } + + @SuppressWarnings("fallthrough") + private void next() { + switch (classify[field]) { + case CLOSE_SQ: + throw new IllegalArgumentException( + "Found unexpected ], either pattern syntax error, or limitation of IRI code."); + case OPEN_SQ: + add(); + untilCloseSq(); + break; + case OPEN_VAR: + field++; + rslt.append("("); + groupCount++; + if (split[field].equals("host")) { + addHost(); + } else { + if (split[field].equals("shouldLowerCase")) { + + shouldLowerCase |= (1 << groupCount); + } else if (split[field].equals("mustLowerCase")) { + + mustLowerCase |= (1 << groupCount); + } else { + throw new IllegalArgumentException("No macro: " + + split[field]); + } + addLowerCase(); + } + break; + + case OPEN_PAREN: + groupCount++; + // fall through + case OPEN_NON_CAPTURING_PAREN: + case CLOSE_PAREN: + case CLOSE_BRACE: + case LOWER_CASE_RANGE: + case OTHER: + add(); + return; + default: + throw new IllegalStateException("IRI code internal error."); + } + } + + @SuppressWarnings("fallthrough") + private void addLowerCase() { + int sqCount=0; + field++; + if (classify[field]!=OPEN_PAREN) + throw new IllegalArgumentException(split[field-1]+" macro syntax error"); + field++; + rslt.append("?:(?:"); // make group non-capturing. + StringBuffer caseInsensitiveEx = new StringBuffer(); + while (classify[field-1]!=CLOSE_PAREN || sqCount>0 ) { + if (field >= split.length) + throw new IllegalArgumentException( + "Internal IRI code error. Did not find CLOSE_PAREN in addLowerCase()."); + + switch (classify[field]) { + case OPEN_SQ: + sqCount++; + caseInsensitiveEx.append('['); + break; + case CLOSE_SQ: + sqCount--; + caseInsensitiveEx.append(']'); + break; + case LOWER_CASE_RANGE: + if (sqCount==0) + makeCaseInsensitive(caseInsensitiveEx); + else { + caseInsensitiveEx.append(split[field]); + caseInsensitiveEx.append((char)(split[field].charAt(0)-'a'+'A')); + caseInsensitiveEx.append('-'); + caseInsensitiveEx.append((char)(split[field].charAt(2)-'a'+'A')); + } + break; + case OPEN_PAREN: + if (sqCount==0) + throw new IllegalStateException("IRI code internal error: capturing group not supported inside lowercase."); + // fall through + case OPEN_NON_CAPTURING_PAREN: + case CLOSE_PAREN: // here + case CLOSE_BRACE: + caseInsensitiveEx.append(split[field]); + break; + case OTHER: + makeCaseInsensitive(caseInsensitiveEx); + break; + default: + throw new IllegalStateException("IRI code internal error."); + } + add(); + } + if (classify[field]!=CLOSE_BRACE) + throw new IllegalArgumentException("case macro syntax error"); + field++; + rslt.append("|("); // start capturing group + rslt.append(caseInsensitiveEx); + rslt.append(")"); + } + + private void makeCaseInsensitive(StringBuffer caseInsensitiveEx) { + for (int i=0;i<split[field].length();i++) { + char c = split[field].charAt(i); + if (c>='a' && c<='z') { + caseInsensitiveEx.append('['); + caseInsensitiveEx.append(c); + caseInsensitiveEx.append((char)(c-'a'+'A')); + caseInsensitiveEx.append(']'); + } + } + } + + private void addHost() { + hostNames |= (1 << groupCount); + field++; + if (classify[field]!=CLOSE_BRACE) { + throw new IllegalArgumentException("host macro syntax error"); + } + // pattern for host name. A sequence of chars that are not reserved. + // or an IP v6 or future address which starts and ends with [ ] and may + // include :. + rslt.append("[^\\[\\]:/?#@!$&'()*+,;=]*|\\[[^\\[\\]/?#@!$&'()*+,;=]*\\])"); + field++; + } + + private void add() { + rslt.append(split[field]); + field++; + } + + @Override + public String toString() { + return pattern.pattern(); + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java new file mode 100644 index 0000000..19df2dd --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java @@ -0,0 +1,33 @@ +/* + * 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.jena.iri.impl; + +import java.util.regex.Matcher; + +public class ErrorAction extends GroupAction { + final private int eCode; + ErrorAction(int code){ + this.eCode = code; + } + @Override + public void check(Matcher m, Parser parser, int range) { + parser.recordError(range,eCode); + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java new file mode 100644 index 0000000..0a56142 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java @@ -0,0 +1,35 @@ +/* + * 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.jena.iri.impl; + +public interface Force { + static final int SHOULD = 0; + static final int DNS = 1; + static final int MINTING = 2; + static final int SECURITY = 3; +// static final int SCHEME_SPECIFIC = 4; + static final int MUST = 4; + static final int SIZE = 5; + static final int minting = 1 << MINTING; + static final int must = 1 << MUST; + static final int should = 1 << SHOULD; + static final int dns = 1 << DNS; + static final int security = 1 << SECURITY; + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java new file mode 100644 index 0000000..b1c03eb --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java @@ -0,0 +1,33 @@ +/* + * 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.jena.iri.impl; + +import java.util.regex.Matcher; + +public abstract class GroupAction { + + public static final GroupAction NoAction = new GroupAction() { + @Override + public void check(Matcher m, Parser parser, int range) { + } + }; + + abstract public void check(Matcher m, Parser parser, int range); + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java new file mode 100644 index 0000000..40cc55c --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java @@ -0,0 +1,34 @@ +/* + * 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.jena.iri.impl; + +import java.util.regex.Matcher; + +public class HostAction extends GroupAction { + final private int group; + HostAction(int group) { + this.group = group; + } + @Override + public void check(Matcher m, Parser parser, int range) { + Parser.hostLexer().analyse(parser,range,m.group(group)); + + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java new file mode 100644 index 0000000..fdf1c46 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012 The Apache Software Foundation. + * + * Licensed 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.jena.iri.impl; + +import java.net.IDN; + +/** + * IDNP: IDN Patched + * + * A wrapper around java.net.IDN to avoid a bug when checking result. + * It looks like the IDN is apply checks before fully converting, so this defers + * a similar check until the end. + */ +public class IDNP { + + public static String toASCII(String host, int flags) { + if ((flags & IDN.USE_STD3_ASCII_RULES) != 0) { + return check(IDN.toASCII(host, flags ^ IDN.USE_STD3_ASCII_RULES)); + } else { + return IDN.toASCII(host, flags); + } + } + + // Step through each part of the host and ensure that they conform + private static String check(final String asciiHost) { + String[] parts = asciiHost.split("\\."); + for (String part: parts) checkPart(part); + return asciiHost; + } + + // Part check: no leading or trailing hyphens, hyphens and alphanumerics. + // We try to follow java.net.IDN behaviour in our exceptions, in anticipation + // of dumping this class. + private static void checkPart(String part) { + if (part.charAt(0) == '-' || + part.charAt(part.length() - 1) == '-') { + throw new IllegalArgumentException("Has leading or trailing hyphen"); + } + for (int i = 0; i < part.length(); i++) { + char c = part.charAt(i); + // Host is limited to hyphens and alpha numerics + if (c != '-' && + !(c >= '0' && c <= '9') && + !(c >= 'a' && c <= 'z') && + !(c >= 'A' && c <= 'Z')) { + throw new IllegalArgumentException("Contains non-LDH characters"); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java new file mode 100644 index 0000000..442b6dd --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java @@ -0,0 +1,40 @@ +/* + * 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.jena.iri.impl; + +public class IRIExamples { + + protected final String badExamples[]; + protected final String goodExamples[]; + + public IRIExamples(String[] badExamples, String[] goodExamples) { + + this.badExamples = badExamples; + this.goodExamples = goodExamples; + } + + public String[] getBadExamples() { + return badExamples; + } + + public String[] getGoodExamples() { + return goodExamples; + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java new file mode 100644 index 0000000..ad45840 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java @@ -0,0 +1,498 @@ +/* + * 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.jena.iri.impl; + +import java.io.UnsupportedEncodingException; +import java.util.AbstractSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import org.apache.jena.iri.IRI ; +import org.apache.jena.iri.IRIComponents ; +import org.apache.jena.iri.ViolationCodes ; + + +public class IRIFactoryImpl + extends AbsIRIFactoryImpl + implements ViolationCodes, Force, IRIComponents { + +public static final int UNKNOWN_SYNTAX = -4; + // boolean throwUncheckedExceptions = false; + /* + static final long conformanceMasks[] = { + // RFC3986 + (1l<<ILLEGAL_CHAR) + |(1l<<ILLEGAL_PERCENT_ENCODING) + |(1l<<EMPTY_SCHEME) + |(1l<<IP_V4_HAS_FOUR_COMPONENTS) + |(1l<<IP_V4_OCTET_RANGE) + |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX) + |(1l<<IRI_CHAR) + |(1l<<LTR_CHAR) + |(1l<<NOT_XML_SCHEMA_WHITESPACE) + |(1l<<SCHEME_MUST_START_WITH_LETTER) + |(1l<<UNWISE_CHAR) + |(1l<<WHITESPACE) + |(1l<<ARBITRARY_CHAR) + , + // RFC3987 + (1l<<ILLEGAL_CHAR) + |(1l<<ILLEGAL_PERCENT_ENCODING) + |(1l<<EMPTY_SCHEME) + |(1l<<IP_V4_HAS_FOUR_COMPONENTS) + |(1l<<IP_V4_OCTET_RANGE) + |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX) + |(1l<<LTR_CHAR) + |(1l<<NOT_XML_SCHEMA_WHITESPACE) + |(1l<<SCHEME_MUST_START_WITH_LETTER) + |(1l<<UNWISE_CHAR) + |(1l<<WHITESPACE) + |(1l<<ARBITRARY_CHAR) + , + // RDF + (1l<<ILLEGAL_CHAR) + |(1l<<ILLEGAL_PERCENT_ENCODING) + |(1l<<EMPTY_SCHEME) + |(1l<<IP_V4_HAS_FOUR_COMPONENTS) + |(1l<<IP_V4_OCTET_RANGE) + |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX) + |(1l<<SCHEME_MUST_START_WITH_LETTER) + |(1l<<RELATIVE_URI) + , + // XLink + (1l<<ILLEGAL_CHAR) + |(1l<<ILLEGAL_PERCENT_ENCODING) + |(1l<<EMPTY_SCHEME) + |(1l<<IP_V4_HAS_FOUR_COMPONENTS) + |(1l<<IP_V4_OCTET_RANGE) + |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX) + |(1l<<SCHEME_MUST_START_WITH_LETTER) + |(1l<<NON_XML_CHARACTER) + , + // XMLSchema + (1l<<ILLEGAL_CHAR) + |(1l<<ILLEGAL_PERCENT_ENCODING) + |(1l<<EMPTY_SCHEME) + |(1l<<IP_V4_HAS_FOUR_COMPONENTS) + |(1l<<IP_V4_OCTET_RANGE) + |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX) + |(1l<<SCHEME_MUST_START_WITH_LETTER) + |(1l<<NOT_XML_SCHEMA_WHITESPACE) + |(1l<<NON_XML_CHARACTER) + , + // IDN +// (1l<<ACE_PREFIX) + 0 + , + // Should + (1l<<LOWERCASE_PREFERRED) + |(1l<<PORT_SHOULD_NOT_BE_EMPTY) + |(1l<<PORT_SHOULD_NOT_START_IN_ZERO) + // |(1l<<SCHEME_NAMES_SHOULD_BE_LOWER_CASE) + |(1l<<PERCENT_ENCODING_SHOULD_BE_UPPERCASE) + |(1l<<IPv6ADDRESS_SHOULD_BE_LOWERCASE) + |(1l<<USE_PUNYCODE_NOT_PERCENTS) + , + // Minting + /* consider HAS_PASSWORD vs LOWER_CASE_PREFERRED + * The former should be an error unless switched + * off (but it can be, unlike a MUST), whereas the + * latter should be a warning by default. + * / + (1l<<LOWERCASE_PREFERRED) + |(1l<<PORT_SHOULD_NOT_BE_EMPTY) + |(1l<<PORT_SHOULD_NOT_START_IN_ZERO) + // |(1l<<SCHEME_NAMES_SHOULD_BE_LOWER_CASE) + |(1l<<PERCENT_ENCODING_SHOULD_BE_UPPERCASE) + |(1l<<IPv6ADDRESS_SHOULD_BE_LOWERCASE) + |(1l<<USE_PUNYCODE_NOT_PERCENTS) + , + // DNS + (1l<<NOT_DNS_NAME) + , + }; + */ + protected long errors; + protected long warnings; + + protected Set<Specification> specs = new HashSet<>(); + + public IRIFactoryImpl() { + } + + public IRIFactoryImpl(IRIFactoryImpl template) { + if (backwardCompatibleRelativeRefs.size()==Integer.MAX_VALUE) + backwardCompatibleRelativeRefs = template.backwardCompatibleRelativeRefs; + else + backwardCompatibleRelativeRefs = new HashSet<>(backwardCompatibleRelativeRefs); + encoding = template.encoding; + errors = template.errors; + prohibited = template.prohibited; + required = template.required; + warnings = template.warnings; + System.arraycopy(template.asErrors,0,asErrors,0,asErrors.length); + System.arraycopy(template.asWarnings,0,asWarnings,0,asWarnings.length); + for ( Entry<String, SchemeSpecificPart> entry : template.schemes.entrySet() ) + { + SchemeSpecificPart p = entry.getValue(); + if ( p.withScheme() ) + { + schemes.put( entry.getKey(), new WithScheme( (WithScheme) p ) ); + } + else if ( p.port() != IRI.NO_PORT ) + { + schemes.put( entry.getKey(), new NoScheme( p.port() ) ); + } + } + } + + /* + protected long recsToMask(int recs) { + long mask = 0; + for (int i=0; recs != 0 && i<conformanceMasks.length; i++) { + if ((recs & (1<<i)) != 0) { + mask |= conformanceMasks[i]; + recs &= ~(1<<i); + } + } + return mask; + } +*/ + private final long getMask(boolean includeWarnings) { + + return includeWarnings?(errors|warnings):errors; + } + + @Override + protected IRIFactoryImpl getFactory() { + return this; + } + + @Override + public IRI create(IRI i) { + if (i instanceof AbsIRIImpl && + ((AbsIRIImpl)i).getFactory()==this) + return i; + return + create(i.toString()); + } + + boolean getSameSchemaRelativeReferences(String scheme) { + return backwardCompatibleRelativeRefs.contains(scheme.toLowerCase()); + } + + private String encoding = "utf-8"; + String getEncoding() { + return encoding; + } + public void setEncoding(String enc) throws UnsupportedEncodingException { + // check enc is valid encoding. + "".getBytes(enc); + encoding = enc; + } + + + boolean asErrors[] = new boolean[]{ + true, + true, + false, + true, + true, + true, + + }; + boolean asWarnings[] = new boolean[]{ + false, + false, + true, + false, + false, + false + }; + + protected void setViolation(int ix, boolean e, boolean w){ + if (e && w) + throw new IllegalArgumentException("xxxViolation(true,true) is not permitted."); + initializing(); + asErrors[ix]=e; + asWarnings[ix]=w; + + } + + protected boolean getAsWarnings(int ix) { + return asWarnings[ix]; + } + + protected boolean getAsErrors(int ix) { + return asErrors[ix]; + } +// boolean isException(int code) { +// return (errors & (1l<<code))!=0; +// } + + private boolean initializing = true; +private Set<String> backwardCompatibleRelativeRefs = new HashSet<>(); + protected void initializing() { + if (!initializing) + throw new IllegalStateException("Cannot reinitialize IRIFactory after first use."); + + } + + @Override + public IRI create(String s) { + initializing = false; + return super.create(s); + } + + public void setSameSchemeRelativeReferences(String scheme) { + if (scheme.equals("*")) + backwardCompatibleRelativeRefs = new AbstractSet<String>(){ + + @Override + public int size() { + return Integer.MAX_VALUE; + } + + @Override + public Iterator<String> iterator() { + throw new UnsupportedOperationException(); + } + @Override + public boolean add(String o) { + return false; + } + + @Override + public boolean contains(Object o) { + return true; + } + }; + else + backwardCompatibleRelativeRefs.add(scheme.toLowerCase()); + } + + protected void useSpec(String name, boolean asErr) { + initializing(); + Specification spec = Specification.get(name); + specs.add(spec); + for (int i=0; i<Force.SIZE; i++) { + if (asErrors[i] || (asWarnings[i] && asErr)) { + errors |= spec.getErrors(i); + } + if (asWarnings[i] ) { + warnings |= spec.getErrors(i); + } + } + prohibited |= spec.getProhibited(); + required |= spec.getRequired(); + warnings &= ~errors; + + } + + public SchemeSpecificPart getScheme(String scheme, Parser parser) { + + scheme = scheme.toLowerCase(); + SchemeSpecificPart p = schemes.get(scheme); + if (p!=null) { + p.usedBy(parser); + return p; + } + int dash = scheme.indexOf('-'); + if (dash != -1) { + if (scheme.startsWith("x-")) { + p = noScheme(); + } else { + if (nonIETFScheme==null) + nonIETFScheme = new NoScheme() { + @Override void usedBy(Parser pp) { + pp.recordError(SCHEME,UNREGISTERED_NONIETF_SCHEME_TREE); + } + }; + p = nonIETFScheme; + } + } else if (Specification.schemes.containsKey(scheme)) { + SchemeSpecification spec = (SchemeSpecification)Specification.schemes.get(scheme); + p = new NoScheme(spec.port); + } else{ + if (unregisteredScheme==null){ + unregisteredScheme = new NoScheme() { + @Override void usedBy(Parser pp) { + pp.recordError(SCHEME,UNREGISTERED_IANA_SCHEME); + } + }; + } + p= unregisteredScheme; + } + p.usedBy(parser); +// System.err.println("Scheme: "+scheme); + if (schemes.size() < 1000) + schemes.put(scheme,p); + return p; + } + + private NoScheme unregisteredScheme=null; + private NoScheme nonIETFScheme=null; + + public SchemeSpecificPart noScheme() { + return noScheme; + } + private class WithScheme extends SchemeSpecificPart + { + long zerrors; + long zwarnings; + int zrequired; + int zprohibited; + boolean inited = false; + final SchemeSpecification scheme; + private WithScheme(WithScheme ws) { + zerrors = ws.zerrors; + zwarnings = ws.zwarnings; + zprohibited = ws.zprohibited; + zrequired = ws.zrequired; + scheme = ws.scheme; + } + private WithScheme(SchemeSpecification spec, boolean asErr){ + scheme = spec; + for (int i=0; i<Force.SIZE; i++) { + if (asErrors[i] || (asWarnings[i] && asErr)) { + zerrors |= spec.getErrors(i); + } + if (asWarnings[i] ) { + zwarnings |= spec.getErrors(i); + } + } + + } + @Override void usedBy(Parser parser) { + if (!inited) { + inited = true; + zerrors |= errors; + zwarnings |= warnings; + zwarnings &= ~zerrors; + zrequired = scheme.getRequired() | required; + zprohibited = scheme.getProhibited() | prohibited; + } + + } + @Override + public long getMask(boolean includeWarnings) { + return includeWarnings?(zerrors|zwarnings):zerrors; + } + @Override + public int getRequired() { + return zrequired; + } + @Override + public int getProhibited() { + return zprohibited; + } + @Override + public void analyse(Parser parser, int range) { + scheme.analyse(parser,range); + } + @Override + public int port() { + return scheme.port; + } + @Override + public boolean withScheme() { + return true; + } + + } + private class NoScheme extends SchemeSpecificPart { + + NoScheme() { + this(-1); + } + final private int port; + NoScheme(int i) { + port = i; + } + @Override + public long getMask(boolean includeWarnings) { + return IRIFactoryImpl.this.getMask(includeWarnings); + } + @Override + public int getRequired() { + return IRIFactoryImpl.this.getRequired(); + } + @Override + public int getProhibited() { + return IRIFactoryImpl.this.getProhibited(); + } + @Override + void usedBy(Parser parser) { /* nothing */ } + @Override + public void analyse(Parser parser, int range) {/* nothing */ } + @Override + public int port() { + return port; + } + @Override + public boolean withScheme() { + return false; + } + + } + + final private NoScheme noScheme = new NoScheme(); + private int required = 0; + private int prohibited = 0; + + public int getRequired() { + return required; + } + + public int getProhibited() { + return prohibited ; + } + + final private Map<String, SchemeSpecificPart> schemes = new HashMap<>(); + + public void useSchemeSpecificRules(String scheme, boolean asErr) + { + if (scheme.equals("*")) + { + for ( String s : Specification.schemes.keySet() ) + { + scheme = s; + if ( !schemes.containsKey( scheme ) ) + { + useSchemeSpecificRules( scheme, asErr ); + } + } + return ; + } + scheme = scheme.toLowerCase() ; + SchemeSpecification spec = (SchemeSpecification) Specification.schemes.get(scheme) ; + if (spec == null) + { + schemes.put(scheme, noScheme) ; + } else + { + schemes.put(scheme, new WithScheme(spec, asErr)) ; + } + + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java new file mode 100644 index 0000000..f2dc6bf --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.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.jena.iri.impl; + + +import org.apache.jena.iri.IRIComponents ; +import org.apache.jena.iri.IRIFactory ; + +public class IRIImpl + extends AbsIRIImpl +implements IRIComponents { + + final IRIFactoryImpl factory; + final String original; + final Parser parser; + Exception idnaException; + + SchemeSpecificPart scheme; + + public IRIImpl(IRIFactory f) { + this(f,"" +// ,NO_EXCEPTIONS + ); + } + +// IRIImpl(IRIFactoryImpl f, String s) { +// this(f,s,ALL_EXCEPTIONS); +// +// } + +// private IRIImpl(IRIFactory f, IRIImpl b, IRI r) { +// factory = f; +// +// // implement relative URI stuff ... +// +// if (b.original.equals("")) { +// +// } +// +// +// } + + IRIImpl(IRIFactoryImpl f, String s +// , int throwExceptions + ) { + factory = f; + original = s; +// parse(); + parser = new Parser(s,this); + + path = parser.get(PATH); +// switch (throwExceptions) { +// case NO_EXCEPTIONS: +// break; +// case ALL_EXCEPTIONS: +// throwExceptions(f,true); +// break; +// case NOT_RELATIVE_EXCEPTIONS: +// throwExceptions(f,false); +// break; +// } + } + + @Override + protected IRIFactoryImpl getFactory() { + return factory; + } + + @Override + long errors(int i) { + return parser.errors(i); + } + + @Override + boolean has(int component) { + return parser.has(component); + } + + @Override + String get(int comp) { + return parser.get(comp); + } + + @Override + String pathRemoveDots() { + if (dotsOK()) + return path; + return removeDotSegments(path); + } + + @Override + boolean dotsOK() { + return (errors(PATH)&(1l<<NON_INITIAL_DOT_SEGMENT))==0; + } + + @Override + public String toString() { + return original; + } + + @Override + SchemeSpecificPart getSchemeSpec() { + return scheme; + } + + @Override + Exception getIDNAException() { + return idnaException; + } + + + + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java new file mode 100644 index 0000000..a0b9c40 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java @@ -0,0 +1,44 @@ +/* + * 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.jena.iri.impl; + +import org.apache.jena.iri.IRIException ; +import org.apache.jena.iri.Violation ; + +public class IRIImplException extends IRIException { + + private static final long serialVersionUID = 1072420548744246731L; + private final Violation violation; + + @Override + public Violation getViolation() { + return violation; + } + public IRIImplException(Violation e) { + super(); + violation = e; + } + + @Override + public String getMessage() { + return getViolation().getShortMessage(); + } + + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java new file mode 100644 index 0000000..db86a34 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java @@ -0,0 +1,25 @@ +/* + * 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.jena.iri.impl; + +interface Lexer { + + void analyse(Parser parser, int i); + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java ---------------------------------------------------------------------- diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java new file mode 100644 index 0000000..10124f9 --- /dev/null +++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java @@ -0,0 +1,30 @@ +/* + * 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.jena.iri.impl; + +import java.io.Reader; + + +class LexerFragment extends LexerQuery { + + LexerFragment(Reader reader) { + super(reader); + } + +}
