Update Dependancies

This commit is contained in:
ME1312 2018-01-21 21:49:18 -05:00
parent eb18c01b22
commit cc1f86c4d1
131 changed files with 298 additions and 15518 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -86,6 +86,10 @@
<dd>
<div class="block">Add an extra value to this Server</div>
</dd>
<dt><span class="memberNameLink"><a href="net/ME1312/SubServers/Host/SubAPI.html#addListener-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Object...-">addListener(SubPluginInfo, Object...)</a></span> - Method in class net.ME1312.SubServers.Host.<a href="net/ME1312/SubServers/Host/SubAPI.html" title="class in net.ME1312.SubServers.Host">SubAPI</a></dt>
<dd>
<div class="block">Register SubEvent Listeners</div>
</dd>
<dt><a href="net/ME1312/SubServers/Host/Network/Encryption/AES.html" title="class in net.ME1312.SubServers.Host.Network.Encryption"><span class="typeNameLink">AES</span></a> - Class in <a href="net/ME1312/SubServers/Host/Network/Encryption/package-summary.html">net.ME1312.SubServers.Host.Network.Encryption</a></dt>
<dd>
<div class="block">A class to perform password-based AES encryption and decryption in CBC mode.</div>

View File

@ -17,7 +17,7 @@
catch(err) {
}
//-->
var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":9,"i6":42,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10};
var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":9,"i7":42,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10};
var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]};
var altColor = "altColor";
var rowColor = "rowColor";
@ -137,35 +137,42 @@ extends java.lang.Object</pre>
</tr>
<tr id="i1" class="rowColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#addListener-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Object...-">addListener</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Object...&nbsp;listeners)</code>
<div class="block">Register SubEvent Listeners</div>
</td>
</tr>
<tr id="i2" class="altColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#cancelTask-java.util.UUID-">cancelTask</a></span>(java.util.UUID&nbsp;sid)</code>
<div class="block">Cancel a task</div>
</td>
</tr>
<tr id="i2" class="altColor">
<tr id="i3" class="rowColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#executeEvent-net.ME1312.SubServers.Host.Library.Event.Event-">executeEvent</a></span>(<a href="../../../../net/ME1312/SubServers/Host/Library/Event/Event.html" title="class in net.ME1312.SubServers.Host.Library.Event">Event</a>&nbsp;event)</code>
<div class="block">Run a SubEvent</div>
</td>
</tr>
<tr id="i3" class="rowColor">
<tr id="i4" class="altColor">
<td class="colFirst"><code><a href="../../../../net/ME1312/SubServers/Host/Library/Version/Version.html" title="class in net.ME1312.SubServers.Host.Library.Version">Version</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getAppVersion--">getAppVersion</a></span>()</code>
<div class="block">Gets the SubServers Version</div>
</td>
</tr>
<tr id="i4" class="altColor">
<tr id="i5" class="rowColor">
<td class="colFirst"><code><a href="../../../../net/ME1312/SubServers/Host/Library/Version/Version.html" title="class in net.ME1312.SubServers.Host.Library.Version">Version</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getBetaVersion--">getBetaVersion</a></span>()</code>
<div class="block">Gets the SubServers Beta Version</div>
</td>
</tr>
<tr id="i5" class="rowColor">
<tr id="i6" class="altColor">
<td class="colFirst"><code>static <a href="../../../../net/ME1312/SubServers/Host/SubAPI.html" title="class in net.ME1312.SubServers.Host">SubAPI</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getInstance--">getInstance</a></span>()</code>
<div class="block">Gets the SubAPI Methods</div>
</td>
</tr>
<tr id="i6" class="altColor">
<tr id="i7" class="rowColor">
<td class="colFirst"><code><a href="../../../../net/ME1312/SubServers/Host/ExHost.html" title="class in net.ME1312.SubServers.Host">ExHost</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getInternals--">getInternals</a></span>()</code>
<div class="block"><span class="deprecatedLabel">Deprecated.</span>&nbsp;
@ -173,70 +180,70 @@ extends java.lang.Object</pre>
</div>
</td>
</tr>
<tr id="i7" class="rowColor">
<tr id="i8" class="altColor">
<td class="colFirst"><code>java.util.Map&lt;java.lang.String,java.lang.String&gt;</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getLang-java.lang.String-">getLang</a></span>(java.lang.String&nbsp;channel)</code>
<div class="block">Gets values from the SubServers Lang</div>
</td>
</tr>
<tr id="i8" class="altColor">
<tr id="i9" class="rowColor">
<td class="colFirst"><code>java.lang.String</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getLang-java.lang.String-java.lang.String-">getLang</a></span>(java.lang.String&nbsp;channel,
java.lang.String&nbsp;key)</code>
<div class="block">Gets a value from the SubServers Lang</div>
</td>
</tr>
<tr id="i9" class="rowColor">
<tr id="i10" class="altColor">
<td class="colFirst"><code>java.util.Collection&lt;java.lang.String&gt;</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getLangChannels--">getLangChannels</a></span>()</code>
<div class="block">Gets the current SubServers Lang Channels</div>
</td>
</tr>
<tr id="i10" class="altColor">
<tr id="i11" class="rowColor">
<td class="colFirst"><code><a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getPlugin-java.lang.String-">getPlugin</a></span>(java.lang.String&nbsp;plugin)</code>
<div class="block">Gets a Plugin</div>
</td>
</tr>
<tr id="i11" class="rowColor">
<tr id="i12" class="altColor">
<td class="colFirst"><code>java.util.Map&lt;java.lang.String,<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&gt;</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getPlugins--">getPlugins</a></span>()</code>
<div class="block">Get a map of the Plugins</div>
</td>
</tr>
<tr id="i12" class="altColor">
<tr id="i13" class="rowColor">
<td class="colFirst"><code><a href="../../../../net/ME1312/SubServers/Host/Library/UniversalFile.html" title="class in net.ME1312.SubServers.Host.Library">UniversalFile</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getRuntimeDirectory--">getRuntimeDirectory</a></span>()</code>
<div class="block">Gets the Runtime Directory</div>
</td>
</tr>
<tr id="i13" class="rowColor">
<tr id="i14" class="altColor">
<td class="colFirst"><code><a href="../../../../net/ME1312/SubServers/Host/Network/SubDataClient.html" title="class in net.ME1312.SubServers.Host.Network">SubDataClient</a></code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#getSubDataNetwork--">getSubDataNetwork</a></span>()</code>
<div class="block">Gets the SubData Network Manager</div>
</td>
</tr>
<tr id="i14" class="altColor">
<tr id="i15" class="rowColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#removeCommand-java.lang.String...-">removeCommand</a></span>(java.lang.String...&nbsp;handles)</code>
<div class="block">Unregisters a Command</div>
</td>
</tr>
<tr id="i15" class="rowColor">
<tr id="i16" class="altColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#removeListener-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Object...-">removeListener</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Object...&nbsp;listeners)</code>
<div class="block">Unregister SubEvent Listeners</div>
</td>
</tr>
<tr id="i16" class="altColor">
<tr id="i17" class="rowColor">
<td class="colFirst"><code>java.util.UUID</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#schedule-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Runnable-">schedule</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Runnable&nbsp;run)</code>
<div class="block">Schedule a task</div>
</td>
</tr>
<tr id="i17" class="rowColor">
<tr id="i18" class="altColor">
<td class="colFirst"><code>java.util.UUID</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#schedule-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Runnable-long-">schedule</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Runnable&nbsp;run,
@ -244,7 +251,7 @@ extends java.lang.Object</pre>
<div class="block">Schedule a task</div>
</td>
</tr>
<tr id="i18" class="altColor">
<tr id="i19" class="rowColor">
<td class="colFirst"><code>java.util.UUID</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#schedule-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Runnable-long-long-">schedule</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Runnable&nbsp;run,
@ -253,7 +260,7 @@ extends java.lang.Object</pre>
<div class="block">Schedule a task</div>
</td>
</tr>
<tr id="i19" class="rowColor">
<tr id="i20" class="altColor">
<td class="colFirst"><code>java.util.UUID</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#schedule-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Runnable-java.util.concurrent.TimeUnit-long-long-">schedule</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Runnable&nbsp;run,
@ -263,7 +270,7 @@ extends java.lang.Object</pre>
<div class="block">Schedule a task</div>
</td>
</tr>
<tr id="i20" class="altColor">
<tr id="i21" class="rowColor">
<td class="colFirst"><code>java.util.UUID</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../net/ME1312/SubServers/Host/SubAPI.html#schedule-net.ME1312.SubServers.Host.API.SubTask-">schedule</a></span>(<a href="../../../../net/ME1312/SubServers/Host/API/SubTask.html" title="class in net.ME1312.SubServers.Host.API">SubTask</a>&nbsp;builder)</code>
<div class="block">Schedule a task</div>
@ -509,6 +516,22 @@ public&nbsp;<a href="../../../../net/ME1312/SubServers/Host/ExHost.html" title="
</dl>
</li>
</ul>
<a name="addListener-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Object...-">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>addListener</h4>
<pre>public&nbsp;void&nbsp;addListener(<a href="../../../../net/ME1312/SubServers/Host/API/SubPluginInfo.html" title="class in net.ME1312.SubServers.Host.API">SubPluginInfo</a>&nbsp;plugin,
java.lang.Object...&nbsp;listeners)</pre>
<div class="block">Register SubEvent Listeners</div>
<dl>
<dt><span class="paramLabel">Parameters:</span></dt>
<dd><code>plugin</code> - PluginInfo</dd>
<dd><code>listeners</code> - Listeners</dd>
</dl>
</li>
</ul>
<a name="removeListener-net.ME1312.SubServers.Host.API.SubPluginInfo-java.lang.Object...-">
<!-- -->
</a>

Binary file not shown.

Binary file not shown.

View File

@ -140,37 +140,39 @@ public final class SubCommand extends CommandX {
int i = 0;
boolean sent = false;
sender.sendMessage("SubServers > Group/Server List:");
for (String group : plugin.api.getGroups().keySet()) {
String message = "";
message += ChatColor.GOLD + group + ChatColor.RESET + ": ";
List<String> names = new ArrayList<String>();
Map<String, Server> servers = plugin.api.getServers();
for (Server server : plugin.api.getGroup(group)) names.add(server.getName());
Collections.sort(names);
for (String name : names) {
if (i != 0) message += div;
Server server = servers.get(name.toLowerCase());
if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
message += ChatColor.WHITE;
} else if (((SubServer) server).isTemporary()) {
message += ChatColor.AQUA;
} else if (((SubServer) server).isRunning()) {
message += ChatColor.GREEN;
} else if (((SubServer) server).isEnabled() && ((SubServer) server).getCurrentIncompatibilities().size() == 0) {
message += ChatColor.YELLOW;
} else {
message += ChatColor.RED;
if (plugin.api.getGroups().keySet().size() > 0) {
for (String group : plugin.api.getGroups().keySet()) {
String message = "";
message += ChatColor.GOLD + group + ChatColor.RESET + ": ";
List<String> names = new ArrayList<String>();
Map<String, Server> servers = plugin.api.getServers();
for (Server server : plugin.api.getGroup(group)) names.add(server.getName());
Collections.sort(names);
for (String name : names) {
if (i != 0) message += div;
Server server = servers.get(name.toLowerCase());
if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
message += ChatColor.WHITE;
} else if (((SubServer) server).isTemporary()) {
message += ChatColor.AQUA;
} else if (((SubServer) server).isRunning()) {
message += ChatColor.GREEN;
} else if (((SubServer) server).isEnabled() && ((SubServer) server).getCurrentIncompatibilities().size() == 0) {
message += ChatColor.YELLOW;
} else {
message += ChatColor.RED;
}
message += server.getDisplayName() + " (" + server.getAddress().getAddress().getHostAddress() + ':' + server.getAddress().getPort() + ((server.getName().equals(server.getDisplayName())) ? "" : ChatColor.stripColor(div) + server.getName()) + ")";
i++;
}
message += server.getDisplayName() + " (" + server.getAddress().getAddress().getHostAddress() + ':' + server.getAddress().getPort() + ((server.getName().equals(server.getDisplayName()))?"":ChatColor.stripColor(div)+server.getName()) + ")";
i++;
if (i == 0) message += ChatColor.RESET + "(none)";
sender.sendMessage(message);
i = 0;
sent = true;
}
if (i == 0) message += ChatColor.RESET + "(none)";
sender.sendMessage(message);
i = 0;
sent = true;
if (!sent) sender.sendMessage(ChatColor.RESET + "(none)");
sent = false;
}
if (!sent) sender.sendMessage(ChatColor.RESET + "(none)");
sent = false;
sender.sendMessage("SubServers > Host/SubServer List:");
for (Host host : plugin.api.getHosts().values()) {
String message = "";

Binary file not shown.

View File

@ -84,117 +84,119 @@ public final class SubCommand implements CommandExecutor {
if (Class.forName("org.spigotmc.SpigotConfig") != null) spigot.set(true);
}) && spigot.get() && sender instanceof Player) {
net.md_5.bungee.api.chat.TextComponent div = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Command.List.Divider"));
sender.sendMessage(plugin.api.getLang("SubServers", "Command.List.Group-Header"));
for (String group : json.getJSONObject("groups").keySet()) {
List<net.md_5.bungee.api.chat.TextComponent> hoverm = new LinkedList<net.md_5.bungee.api.chat.TextComponent>();
net.md_5.bungee.api.chat.TextComponent msg = new net.md_5.bungee.api.chat.TextComponent(ChatColor.RESET.toString());
net.md_5.bungee.api.chat.TextComponent message = new net.md_5.bungee.api.chat.TextComponent(group);
net.md_5.bungee.api.chat.TextComponent hover = new net.md_5.bungee.api.chat.TextComponent(group + '\n');
message.setColor(net.md_5.bungee.api.ChatColor.GOLD);
hover.setColor(net.md_5.bungee.api.ChatColor.GOLD);
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Group-Menu.Group-Server-Count").replace("$int$", new DecimalFormat("#,###").format(json.getJSONObject("groups").getJSONObject(group).keySet().size())));
hoverm.add(hover);
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, fLabel + " open Server 1 " + group));
message.setHoverEvent(new net.md_5.bungee.api.chat.HoverEvent(net.md_5.bungee.api.chat.HoverEvent.Action.SHOW_TEXT, hoverm.toArray(new net.md_5.bungee.api.chat.TextComponent[hoverm.size()])));
msg.addExtra(message);
msg.addExtra(new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Command.List.Header")));
for (String server : json.getJSONObject("groups").getJSONObject(group).keySet()) {
hoverm = new LinkedList<net.md_5.bungee.api.chat.TextComponent>();
message = new net.md_5.bungee.api.chat.TextComponent(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"));
hover = new net.md_5.bungee.api.chat.TextComponent(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display") + '\n');
if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).keySet().contains("enabled")) {
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, fLabel + " open SubServer/ " + server));
if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("temp")) {
message.setColor(net.md_5.bungee.api.ChatColor.AQUA);
hover.setColor(net.md_5.bungee.api.ChatColor.AQUA);
hoverm.add(hover);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
hoverm.add(hover);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.Server-Player-Count").replace("$int$", new DecimalFormat("#,###").format(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONObject("players").keySet().size())) + '\n');
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Temporary"));
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("running")) {
message.setColor(net.md_5.bungee.api.ChatColor.GREEN);
hover.setColor(net.md_5.bungee.api.ChatColor.GREEN);
hoverm.add(hover);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
hoverm.add(hover);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.Server-Player-Count").replace("$int$", new DecimalFormat("#,###").format(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONObject("players").keySet().size())));
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("enabled") && json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length() == 0) {
message.setColor(net.md_5.bungee.api.ChatColor.YELLOW);
hover.setColor(net.md_5.bungee.api.ChatColor.YELLOW);
hoverm.add(hover);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
hoverm.add(hover);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Offline"));
} else {
message.setColor(net.md_5.bungee.api.ChatColor.RED);
hover.setColor(net.md_5.bungee.api.ChatColor.RED);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
}
if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length() != 0) {
hoverm.add(hover);
String list = "";
for (int ii = 0; ii < json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length(); ii++) {
if (list.length() != 0) list += ", ";
list += json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").getString(ii);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Incompatible").replace("$str$", list));
}
if (!json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("enabled")) {
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Disabled"));
}
}
hoverm.add(hover);
if (plugin.config.get().getSection("Settings").getBoolean("Show-Addresses", false)) {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address"));
} else {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address").split(":")[json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address").split(":").length - 1]);
}
hover.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hoverm.add(hover);
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, fLabel + " open SubServer/ " + server));
} else {
message.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hover.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.Server-External"));
hoverm.add(hover);
if (plugin.config.get().getSection("Settings").getBoolean("Show-Addresses", false)) {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("servers").getJSONObject(server).getString("address"));
} else {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("servers").getJSONObject(server).getString("address").split(":")[json.getJSONObject("servers").getJSONObject(server).getString("address").split(":").length - 1]);
}
hover.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hoverm.add(hover);
}
if (json.getJSONObject("groups").length() > 0) {
sender.sendMessage(plugin.api.getLang("SubServers", "Command.List.Group-Header"));
for (String group : json.getJSONObject("groups").keySet()) {
List<net.md_5.bungee.api.chat.TextComponent> hoverm = new LinkedList<net.md_5.bungee.api.chat.TextComponent>();
net.md_5.bungee.api.chat.TextComponent msg = new net.md_5.bungee.api.chat.TextComponent(ChatColor.RESET.toString());
net.md_5.bungee.api.chat.TextComponent message = new net.md_5.bungee.api.chat.TextComponent(group);
net.md_5.bungee.api.chat.TextComponent hover = new net.md_5.bungee.api.chat.TextComponent(group + '\n');
message.setColor(net.md_5.bungee.api.ChatColor.GOLD);
hover.setColor(net.md_5.bungee.api.ChatColor.GOLD);
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Group-Menu.Group-Server-Count").replace("$int$", new DecimalFormat("#,###").format(json.getJSONObject("groups").getJSONObject(group).keySet().size())));
hoverm.add(hover);
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, fLabel + " open Server 1 " + group));
message.setHoverEvent(new net.md_5.bungee.api.chat.HoverEvent(net.md_5.bungee.api.chat.HoverEvent.Action.SHOW_TEXT, hoverm.toArray(new net.md_5.bungee.api.chat.TextComponent[hoverm.size()])));
if (i != 0) msg.addExtra(div);
msg.addExtra(message);
i++;
msg.addExtra(new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Command.List.Header")));
for (String server : json.getJSONObject("groups").getJSONObject(group).keySet()) {
hoverm = new LinkedList<net.md_5.bungee.api.chat.TextComponent>();
message = new net.md_5.bungee.api.chat.TextComponent(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"));
hover = new net.md_5.bungee.api.chat.TextComponent(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display") + '\n');
if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).keySet().contains("enabled")) {
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, fLabel + " open SubServer/ " + server));
if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("temp")) {
message.setColor(net.md_5.bungee.api.ChatColor.AQUA);
hover.setColor(net.md_5.bungee.api.ChatColor.AQUA);
hoverm.add(hover);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
hoverm.add(hover);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.Server-Player-Count").replace("$int$", new DecimalFormat("#,###").format(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONObject("players").keySet().size())) + '\n');
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Temporary"));
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("running")) {
message.setColor(net.md_5.bungee.api.ChatColor.GREEN);
hover.setColor(net.md_5.bungee.api.ChatColor.GREEN);
hoverm.add(hover);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
hoverm.add(hover);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.Server-Player-Count").replace("$int$", new DecimalFormat("#,###").format(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONObject("players").keySet().size())));
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("enabled") && json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length() == 0) {
message.setColor(net.md_5.bungee.api.ChatColor.YELLOW);
hover.setColor(net.md_5.bungee.api.ChatColor.YELLOW);
hoverm.add(hover);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
hoverm.add(hover);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Offline"));
} else {
message.setColor(net.md_5.bungee.api.ChatColor.RED);
hover.setColor(net.md_5.bungee.api.ChatColor.RED);
if (!server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) {
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(server + '\n');
hover.setColor(net.md_5.bungee.api.ChatColor.GRAY);
}
if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length() != 0) {
hoverm.add(hover);
String list = "";
for (int ii = 0; ii < json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length(); ii++) {
if (list.length() != 0) list += ", ";
list += json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").getString(ii);
}
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Incompatible").replace("$str$", list));
}
if (!json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("enabled")) {
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.SubServer-Disabled"));
}
}
hoverm.add(hover);
if (plugin.config.get().getSection("Settings").getBoolean("Show-Addresses", false)) {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address"));
} else {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address").split(":")[json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address").split(":").length - 1]);
}
hover.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hoverm.add(hover);
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, fLabel + " open SubServer/ " + server));
} else {
message.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hover.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hoverm.add(hover);
hover = new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Interface.Server-Menu.Server-External"));
hoverm.add(hover);
if (plugin.config.get().getSection("Settings").getBoolean("Show-Addresses", false)) {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("servers").getJSONObject(server).getString("address"));
} else {
hover = new net.md_5.bungee.api.chat.TextComponent('\n' + json.getJSONObject("servers").getJSONObject(server).getString("address").split(":")[json.getJSONObject("servers").getJSONObject(server).getString("address").split(":").length - 1]);
}
hover.setColor(net.md_5.bungee.api.ChatColor.WHITE);
hoverm.add(hover);
}
message.setHoverEvent(new net.md_5.bungee.api.chat.HoverEvent(net.md_5.bungee.api.chat.HoverEvent.Action.SHOW_TEXT, hoverm.toArray(new net.md_5.bungee.api.chat.TextComponent[hoverm.size()])));
if (i != 0) msg.addExtra(div);
msg.addExtra(message);
i++;
}
if (i == 0) msg.addExtra(new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Command.List.Empty")));
((Player) sender).spigot().sendMessage(msg);
i = 0;
sent = true;
}
if (i == 0) msg.addExtra(new net.md_5.bungee.api.chat.TextComponent(plugin.api.getLang("SubServers", "Command.List.Empty")));
((Player) sender).spigot().sendMessage(msg);
i = 0;
sent = true;
if (!sent) sender.sendMessage(plugin.api.getLang("SubServers", "Command.List.Empty"));
sent = false;
}
if (!sent) sender.sendMessage(plugin.api.getLang("SubServers", "Command.List.Empty"));
sent = false;
sender.sendMessage(plugin.api.getLang("SubServers", "Command.List.Host-Header"));
for (String host : json.getJSONObject("hosts").keySet()) {
List<net.md_5.bungee.api.chat.TextComponent> hoverm = new LinkedList<net.md_5.bungee.api.chat.TextComponent>();

Binary file not shown.

View File

@ -197,16 +197,19 @@ public class SubPluginInfo implements ExtraDataHandler {
@Override
public void addExtra(String handle, Object value) {
if (Util.isNull(handle, value)) throw new NullPointerException();
extra.set(handle, value);
}
@Override
public boolean hasExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
return extra.getKeys().contains(handle);
}
@Override
public YAMLValue getExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
return extra.get(handle);
}
@ -217,6 +220,7 @@ public class SubPluginInfo implements ExtraDataHandler {
@Override
public void removeExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
extra.remove(handle);
}
}

View File

@ -58,7 +58,7 @@ public final class ExHost {
public SubDataClient subdata = null;
public final Version version = new Version("2.13a");
public final Version bversion = new Version(2);
public final Version bversion = new Version(3);
public final SubAPI api = new SubAPI(this);
private ConsoleReader jline;
@ -178,23 +178,22 @@ public final class ExHost {
}));
creator = new SubCreator(this);
/*
* Find Jars
*/
UniversalFile pldir = new UniversalFile(dir, "Plugins");
if (pldir.exists() && pldir.listFiles().length > 0) {
LinkedList<URL> jars = new LinkedList<URL>();
if (pldir.exists() && pldir.isDirectory()) for (File file : pldir.listFiles()) {
if (file.getName().endsWith(".jar")) {
jars.add(file.toURI().toURL());
}
}
if (jars.size() > 0) {
long begin = Calendar.getInstance().getTime().getTime();
log.info.println("Loading SubAPI Plugins...");
/*
* Find Jars
*/
LinkedList<URL> jars = new LinkedList<URL>();
for (File file : pldir.listFiles()) {
if (file.getName().endsWith(".jar")) {
jars.add(file.toURI().toURL());
}
}
/*
* Find & Pre-Load Main Classes
* Load Jars & Find Main Classes
* (Unordered)
*/
URLClassLoader superloader = new URLClassLoader(jars.toArray(new URL[jars.size()]), this.getClass().getClassLoader());
@ -218,8 +217,6 @@ public final class ExHost {
} catch (Exception e) {
log.error.println(new IllegalPluginException(e, "Couldn't load package.xml for " + file.getName()));
}
} else {
log.error.println(new IllegalPluginException(new FileNotFoundException(), "Couldn't find package.xml for " + file.getName()));
}
boolean isplugin = false;
@ -229,31 +226,35 @@ public final class ExHost {
String cname = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.');
contents.add(cname);
if (mains.contains(cname)) {
mains.remove(cname);
try {
Class<?> clazz = superloader.loadClass(cname);
if (clazz.isAnnotationPresent(SubPlugin.class)) {
NamedContainer<LinkedList<String>, LinkedHashMap<String, String>> jarmap = (classes.keySet().contains(file.getName()))?classes.get(file.getName()):new NamedContainer<LinkedList<String>, LinkedHashMap<String, String>>(new LinkedList<String>(), new LinkedHashMap<>());
for (String dependancy : clazz.getAnnotation(SubPlugin.class).dependencies()) jarmap.name().add(dependancy);
for (String dependancy : clazz.getAnnotation(SubPlugin.class).softDependencies()) jarmap.name().add(dependancy);
jarmap.get().put(clazz.getAnnotation(SubPlugin.class).name(), cname);
classes.put(file.getName(), jarmap);
isplugin = true;
mains.remove(cname);
} else {
log.error.println(new IllegalPluginException(new ClassCastException(), "Main class isn't annotated as a SubPlugin: " + cname));
}
if (!clazz.isAnnotationPresent(SubPlugin.class))
throw new ClassCastException("Cannot find plugin descriptor");
NamedContainer<LinkedList<String>, LinkedHashMap<String, String>> jarmap = (classes.keySet().contains(file.getName()))?classes.get(file.getName()):new NamedContainer<LinkedList<String>, LinkedHashMap<String, String>>(new LinkedList<String>(), new LinkedHashMap<>());
for (String dependancy : clazz.getAnnotation(SubPlugin.class).dependencies()) jarmap.name().add(dependancy);
for (String dependancy : clazz.getAnnotation(SubPlugin.class).softDependencies()) jarmap.name().add(dependancy);
jarmap.get().put(clazz.getAnnotation(SubPlugin.class).name(), cname);
classes.put(file.getName(), jarmap);
isplugin = true;
} catch (ClassCastException e) {
log.error.println(new IllegalPluginException(e, "Main class isn't annotated as a SubPlugin: " + cname));
} catch (Throwable e) {
log.error.println(new IllegalPluginException(e, "Couldn't load main class: " + cname));
}
}
}
}
for (String main : mains) {
log.error.println(new IllegalPluginException(new ClassNotFoundException(), "Couldn't find main class: " + main));
}
if (isplugin) api.knownClasses.addAll(contents);
if (!isplugin) {
new PluginClassLoader(this.getClass().getClassLoader(), file.toURI().toURL());
log.info.println("Loaded Library: " + file.getName());
}
api.knownClasses.addAll(contents);
jar.close();
} catch (Throwable e) {
log.error.println(new InvocationTargetException(e, "Problem searching plugin jar: " + file.getName()));
@ -292,21 +293,21 @@ public final class ExHost {
Object obj = clazz.getConstructor().newInstance();
try {
SubPluginInfo plugin = new SubPluginInfo(this, obj, clazz.getAnnotation(SubPlugin.class).name(), new Version(clazz.getAnnotation(SubPlugin.class).version()),
Arrays.asList(clazz.getAnnotation(SubPlugin.class).authors()), (clazz.getAnnotation(SubPlugin.class).description().length() > 0) ? clazz.getAnnotation(SubPlugin.class).description() : null,
(clazz.getAnnotation(SubPlugin.class).website().length() > 0) ? new URL(clazz.getAnnotation(SubPlugin.class).website()) : null, Arrays.asList(clazz.getAnnotation(SubPlugin.class).loadBefore()),
Arrays.asList(clazz.getAnnotation(SubPlugin.class).authors()), (clazz.getAnnotation(SubPlugin.class).description().length() > 0)?clazz.getAnnotation(SubPlugin.class).description():null,
(clazz.getAnnotation(SubPlugin.class).website().length() > 0)?new URL(clazz.getAnnotation(SubPlugin.class).website()):null, Arrays.asList(clazz.getAnnotation(SubPlugin.class).loadBefore()),
Arrays.asList(clazz.getAnnotation(SubPlugin.class).dependencies()), Arrays.asList(clazz.getAnnotation(SubPlugin.class).softDependencies()));
if (plugins.keySet().contains(plugin.getName().toLowerCase()))
log.warn.println("Duplicate plugin: " + plugin.getName().toLowerCase());
plugin.addExtra("subservers.plugin.loadafter", new ArrayList<String>());
plugins.put(plugin.getName().toLowerCase(), plugin);
} catch (Throwable e) {
log.error.println(new IllegalPluginException(e, "Cannot load plugin descriptor for main class: " + main));
log.error.println(new IllegalPluginException(e, "Couldn't load plugin descriptor for main class: " + main));
}
} catch(ClassCastException e) {
} catch (ClassCastException e) {
log.error.println(new IllegalPluginException(e, "Main class isn't annotated as a SubPlugin: " + main));
} catch(InvocationTargetException e) {
} catch (InvocationTargetException e) {
log.error.println(new IllegalPluginException(e.getTargetException(), "Uncaught exception occurred while loading main class: " + main));
} catch(Throwable e) {
} catch (Throwable e) {
log.error.println(new IllegalPluginException(e, "Couldn't load main class: " + main));
}
loadedlist.add(name);

View File

@ -16,8 +16,8 @@ public class LogStream {
private String name;
private Container<PrintStream> stream;
private boolean first = true;
private Thread threadwriting = null;
protected long writing = 0;
protected Thread threadwriting = null;
protected LogStream(String prefix, String name, Container<PrintStream> stream) {
this.prefix = prefix;
@ -105,17 +105,17 @@ public class LogStream {
first = c == '\n';
}
protected void sync() {
private void stall() {
try {
while (threadwriting != null && threadwriting != Thread.currentThread() && writing > 0) {
while (last != null && last != this && last.writing > 0) {
Thread.sleep(125);
}
} catch (Exception e) {}
}
private void stall() {
protected void sync() {
try {
while (last != null && last != this && last.writing > 0) {
while (threadwriting != null && threadwriting != Thread.currentThread() && writing > 0) {
Thread.sleep(125);
}
} catch (Exception e) {}

View File

@ -10,7 +10,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
* Plugin ClassLoader Class
*/
public class PluginClassLoader extends URLClassLoader {
private static final Set<PluginClassLoader> allLoaders = new CopyOnWriteArraySet<PluginClassLoader>();
private static final Set<PluginClassLoader> loaders = new CopyOnWriteArraySet<PluginClassLoader>();
/**
* Load Classes from URLs
@ -19,7 +19,7 @@ public class PluginClassLoader extends URLClassLoader {
*/
public PluginClassLoader(URL[] urls) {
super(urls);
allLoaders.add(this);
loaders.add(this);
}
/**
@ -30,7 +30,7 @@ public class PluginClassLoader extends URLClassLoader {
*/
public PluginClassLoader(ClassLoader parent, URL... urls) {
super(urls, parent);
allLoaders.add(this);
loaders.add(this);
}
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
@ -42,7 +42,7 @@ public class PluginClassLoader extends URLClassLoader {
return super.loadClass(name, resolve);
} catch (ClassNotFoundException e) {
if (check) {
Iterator i = allLoaders.iterator();
Iterator i = loaders.iterator();
while (true) {
PluginClassLoader loader;

View File

@ -229,7 +229,7 @@ public final class SubAPI {
* @param listeners Listeners
*/
@SuppressWarnings("unchecked")
void addListener(SubPluginInfo plugin, Object... listeners) {
public void addListener(SubPluginInfo plugin, Object... listeners) {
for (Object listener : listeners) {
if (Util.isNull(plugin, listener)) throw new NullPointerException();
for (Method method : Arrays.asList(listener.getClass().getMethods())) {
@ -246,14 +246,16 @@ public final class SubAPI {
events.put((Class<Event>) method.getParameterTypes()[0], plugins);
this.listeners.put(method.getAnnotation(EventHandler.class).order(), events);
} else {
this.host.log.error.println(
"Cannot register EventHandler in class \"" + listener.getClass().getCanonicalName() + "\" using method \"" + method.getName() + "\":",
plugin.getLogger().error.println(
"Cannot register listener \"" + listener.getClass().getCanonicalName() + '.' + method.getName() + "(" + method.getParameterTypes()[0].getCanonicalName() + ")\":",
"\"" + method.getParameterTypes()[0].getCanonicalName() + "\" is not an Event");
}
} else {
this.host.log.error.println(
"Cannot register EventHandler in class \"" + listener.getClass().getCanonicalName() + "\" using method \"" + method.getName() + "\":",
((method.getParameterTypes().length > 0) ? "Too many" : "No") + " parameters for SubEvent to execute");
LinkedList<String> args = new LinkedList<String>();
for (Class<?> clazz : method.getParameterTypes()) args.add(clazz.getCanonicalName());
plugin.getLogger().error.println(
"Cannot register listener \"" + listener.getClass().getCanonicalName() + '.' + method.getName() + "(" + args.toString().substring(1, args.toString().length() - 1) + ")\":",
((method.getParameterTypes().length > 0) ? "Too many" : "No") + " parameters for method to be executed");
}
}
}
@ -310,11 +312,11 @@ public final class SubAPI {
try {
method.invoke(listener, event);
} catch (InvocationTargetException e) {
this.host.log.error.println("Event \"" + method.getName() + "(" + event.getClass().getTypeName() + ")\" in class \"" + listener.getClass().getCanonicalName() + "\" had an unhandled exception:");
this.host.log.error.println(e.getTargetException());
plugin.getLogger().error.println("Event listener \"" + listener.getClass().getCanonicalName() + '.' + method.getName() + "(" + event.getClass().getTypeName() + ")\" had an unhandled exception:");
plugin.getLogger().error.println(e.getTargetException());
} catch (IllegalAccessException e) {
this.host.log.error.println("Cannot access method \"" + method.getName() + "\" in class \"" + listener.getClass().getCanonicalName() + "\"");
this.host.log.error.println(e);
plugin.getLogger().error.println("Cannot access method \"" + listener.getClass().getCanonicalName() + '.' + method.getName() + "(" + event.getClass().getTypeName() + ")\"");
plugin.getLogger().error.println(e);
}
}
}

View File

@ -86,33 +86,35 @@ public class SubCommand {
int i = 0;
boolean sent = false;
String div = TextColor.RESET + ", ";
host.log.message.println("Group/Server List:");
for (String group : json.getJSONObject("groups").keySet()) {
String message = "";
message += TextColor.GOLD + group + TextColor.RESET + ": ";
for (String server : json.getJSONObject("groups").getJSONObject(group).keySet()) {
if (i != 0) message += div;
if (!json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).keySet().contains("enabled")) {
message += TextColor.WHITE;
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("temp")) {
message += TextColor.AQUA;
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("running")) {
message += TextColor.GREEN;
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("enabled") && json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length() == 0) {
message += TextColor.YELLOW;
} else {
message += TextColor.RED;
if (json.getJSONObject("groups").length() > 0) {
host.log.message.println("Group/Server List:");
for (String group : json.getJSONObject("groups").keySet()) {
String message = "";
message += TextColor.GOLD + group + TextColor.RESET + ": ";
for (String server : json.getJSONObject("groups").getJSONObject(group).keySet()) {
if (i != 0) message += div;
if (!json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).keySet().contains("enabled")) {
message += TextColor.WHITE;
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("temp")) {
message += TextColor.AQUA;
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("running")) {
message += TextColor.GREEN;
} else if (json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getBoolean("enabled") && json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getJSONArray("incompatible").length() == 0) {
message += TextColor.YELLOW;
} else {
message += TextColor.RED;
}
message += json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display") + " (" + json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address") + ((server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display"))) ? "" : TextColor.stripColor(div) + server) + ")";
i++;
}
message += json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display") + " (" + json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("address") + ((server.equals(json.getJSONObject("groups").getJSONObject(group).getJSONObject(server).getString("display")))?"":TextColor.stripColor(div)+server) + ")";
i++;
if (i == 0) message += TextColor.RESET + "(none)";
host.log.message.println(message);
i = 0;
sent = true;
}
if (i == 0) message += TextColor.RESET + "(none)";
host.log.message.println(message);
i = 0;
sent = true;
if (!sent) host.log.message.println(TextColor.RESET + "(none)");
sent = false;
}
if (!sent) host.log.message.println(TextColor.RESET + "(none)");
sent = false;
ExHost h = host;
host.log.message.println("Host/SubServer List:");
for (String host : json.getJSONObject("hosts").keySet()) {

View File

@ -1,406 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml;
import java.util.Map;
import java.util.TimeZone;
import org.yaml.snakeyaml.emitter.Emitter;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.serializer.AnchorGenerator;
import org.yaml.snakeyaml.serializer.NumberAnchorGenerator;
public class DumperOptions {
/**
* YAML provides a rich set of scalar styles. Block scalar styles include
* the literal style and the folded style; flow scalar styles include the
* plain style and two quoted styles, the single-quoted style and the
* double-quoted style. These styles offer a range of trade-offs between
* expressive power and readability.
*
* @see <a href="http://yaml.org/spec/1.1/#id903915">Chapter 9. Scalar
* Styles</a>
* @see <a href="http://yaml.org/spec/1.1/#id858081">2.3. Scalars</a>
*/
public enum ScalarStyle {
DOUBLE_QUOTED(Character.valueOf('"')), SINGLE_QUOTED(Character.valueOf('\'')), LITERAL(
Character.valueOf('|')), FOLDED(Character.valueOf('>')), PLAIN(null);
private Character styleChar;
private ScalarStyle(Character style) {
this.styleChar = style;
}
public Character getChar() {
return styleChar;
}
@Override
public String toString() {
return "Scalar style: '" + styleChar + "'";
}
public static ScalarStyle createStyle(Character style) {
if (style == null) {
return PLAIN;
} else {
switch (style) {
case '"':
return DOUBLE_QUOTED;
case '\'':
return SINGLE_QUOTED;
case '|':
return LITERAL;
case '>':
return FOLDED;
default:
throw new YAMLException("Unknown scalar style character: " + style);
}
}
}
}
/**
* Block styles use indentation to denote nesting and scope within the
* document. In contrast, flow styles rely on explicit indicators to denote
* nesting and scope.
*
* @see <a href="http://www.yaml.org/spec/current.html#id2509255">3.2.3.1.
* Node Styles (http://yaml.org/spec/1.1)</a>
*/
public enum FlowStyle {
FLOW(Boolean.TRUE), BLOCK(Boolean.FALSE), AUTO(null);
private Boolean styleBoolean;
private FlowStyle(Boolean flowStyle) {
styleBoolean = flowStyle;
}
public Boolean getStyleBoolean() {
return styleBoolean;
}
@Override
public String toString() {
return "Flow style: '" + styleBoolean + "'";
}
}
/**
* Platform dependent line break.
*/
public enum LineBreak {
WIN("\r\n"), MAC("\r"), UNIX("\n");
private String lineBreak;
private LineBreak(String lineBreak) {
this.lineBreak = lineBreak;
}
public String getString() {
return lineBreak;
}
@Override
public String toString() {
return "Line break: " + name();
}
public static LineBreak getPlatformLineBreak() {
String platformLineBreak = System.getProperty("line.separator");
for (LineBreak lb : values()) {
if (lb.lineBreak.equals(platformLineBreak)) {
return lb;
}
}
return LineBreak.UNIX;
}
}
/**
* Specification version. Currently supported 1.0 and 1.1
*/
public enum Version {
V1_0(new Integer[] { 1, 0 }), V1_1(new Integer[] { 1, 1 });
private Integer[] version;
private Version(Integer[] version) {
this.version = version;
}
public int major() { return version[0]; }
public int minor() { return version[1]; }
public String getRepresentation() {
return version[0] + "." + version[1];
}
@Override
public String toString() {
return "Version: " + getRepresentation();
}
}
private ScalarStyle defaultStyle = ScalarStyle.PLAIN;
private FlowStyle defaultFlowStyle = FlowStyle.AUTO;
private boolean canonical = false;
private boolean allowUnicode = true;
private boolean allowReadOnlyProperties = false;
private int indent = 2;
private int indicatorIndent = 0;
private int bestWidth = 80;
private boolean splitLines = true;
private LineBreak lineBreak = LineBreak.UNIX;
private boolean explicitStart = false;
private boolean explicitEnd = false;
private TimeZone timeZone = null;
private Version version = null;
private Map<String, String> tags = null;
private Boolean prettyFlow = false;
private AnchorGenerator anchorGenerator = new NumberAnchorGenerator(0);
public boolean isAllowUnicode() {
return allowUnicode;
}
/**
* Specify whether to emit non-ASCII printable Unicode characters.
* The default value is true.
* When set to false then printable non-ASCII characters (Cyrillic, Chinese etc)
* will be not printed but escaped (to support ASCII terminals)
*
* @param allowUnicode
* if allowUnicode is false then all non-ASCII characters are
* escaped
*/
public void setAllowUnicode(boolean allowUnicode) {
this.allowUnicode = allowUnicode;
}
public ScalarStyle getDefaultScalarStyle() {
return defaultStyle;
}
/**
* Set default style for scalars. See YAML 1.1 specification, 2.3 Scalars
* (http://yaml.org/spec/1.1/#id858081)
*
* @param defaultStyle
* set the style for all scalars
*/
public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
if (defaultStyle == null) {
throw new NullPointerException("Use ScalarStyle enum.");
}
this.defaultStyle = defaultStyle;
}
public void setIndent(int indent) {
if (indent < Emitter.MIN_INDENT) {
throw new YAMLException("Indent must be at least " + Emitter.MIN_INDENT);
}
if (indent > Emitter.MAX_INDENT) {
throw new YAMLException("Indent must be at most " + Emitter.MAX_INDENT);
}
this.indent = indent;
}
public int getIndent() {
return this.indent;
}
public void setIndicatorIndent(int indicatorIndent) {
if (indicatorIndent < 0) {
throw new YAMLException("Indicator indent must be non-negative.");
}
if (indicatorIndent > Emitter.MAX_INDENT - 1) {
throw new YAMLException("Indicator indent must be at most Emitter.MAX_INDENT-1: " + (Emitter.MAX_INDENT - 1));
}
this.indicatorIndent = indicatorIndent;
}
public int getIndicatorIndent() {
return this.indicatorIndent;
}
public void setVersion(Version version) {
this.version = version;
}
public Version getVersion() {
return this.version;
}
/**
* Force the emitter to produce a canonical YAML document.
*
* @param canonical
* true produce canonical YAML document
*/
public void setCanonical(boolean canonical) {
this.canonical = canonical;
}
public boolean isCanonical() {
return this.canonical;
}
/**
* Force the emitter to produce a pretty YAML document when using the flow
* style.
*
* @param prettyFlow
* true produce pretty flow YAML document
*/
public void setPrettyFlow(boolean prettyFlow) {
this.prettyFlow = prettyFlow;
}
public boolean isPrettyFlow() {
return this.prettyFlow;
}
/**
* Specify the preferred width to emit scalars. When the scalar
* representation takes more then the preferred with the scalar will be
* split into a few lines. The default is 80.
*
* @param bestWidth
* the preferred width for scalars.
*/
public void setWidth(int bestWidth) {
this.bestWidth = bestWidth;
}
public int getWidth() {
return this.bestWidth;
}
/**
* Specify whether to split lines exceeding preferred width for
* scalars. The default is true.
*
* @param splitLines
* whether to split lines exceeding preferred width for scalars.
*/
public void setSplitLines(boolean splitLines) {
this.splitLines = splitLines;
}
public boolean getSplitLines() {
return this.splitLines;
}
public LineBreak getLineBreak() {
return lineBreak;
}
public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
if (defaultFlowStyle == null) {
throw new NullPointerException("Use FlowStyle enum.");
}
this.defaultFlowStyle = defaultFlowStyle;
}
public FlowStyle getDefaultFlowStyle() {
return defaultFlowStyle;
}
/**
* Specify the line break to separate the lines. It is platform specific:
* Windows - "\r\n", old MacOS - "\r", Unix - "\n". The default value is the
* one for Unix.
* @param lineBreak to be used for the input
*/
public void setLineBreak(LineBreak lineBreak) {
if (lineBreak == null) {
throw new NullPointerException("Specify line break.");
}
this.lineBreak = lineBreak;
}
public boolean isExplicitStart() {
return explicitStart;
}
public void setExplicitStart(boolean explicitStart) {
this.explicitStart = explicitStart;
}
public boolean isExplicitEnd() {
return explicitEnd;
}
public void setExplicitEnd(boolean explicitEnd) {
this.explicitEnd = explicitEnd;
}
public Map<String, String> getTags() {
return tags;
}
public void setTags(Map<String, String> tags) {
this.tags = tags;
}
/**
* Report whether read-only JavaBean properties (the ones without setters)
* should be included in the YAML document
*
* @return false when read-only JavaBean properties are not emitted
*/
public boolean isAllowReadOnlyProperties() {
return allowReadOnlyProperties;
}
/**
* Set to true to include read-only JavaBean properties (the ones without
* setters) in the YAML document. By default these properties are not
* included to be able to parse later the same JavaBean.
*
* @param allowReadOnlyProperties
* - true to dump read-only JavaBean properties
*/
public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
this.allowReadOnlyProperties = allowReadOnlyProperties;
}
public TimeZone getTimeZone() {
return timeZone;
}
/**
* Set the timezone to be used for Date. If set to <code>null</code> UTC is
* used.
* @param timeZone for created Dates or null to use UTC
*/
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
public AnchorGenerator getAnchorGenerator() {
return anchorGenerator;
}
public void setAnchorGenerator(AnchorGenerator anchorGenerator) {
this.anchorGenerator = anchorGenerator;
}
}

View File

@ -1,45 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml;
public class LoaderOptions {
private boolean allowDuplicateKeys = true;
public boolean isAllowDuplicateKeys() {
return allowDuplicateKeys;
}
/**
* Allow/Reject duplicate map keys in the YAML file.
*
* Default is to allow.
*
* YAML 1.1 is slightly vague around duplicate entries in the YAML file. The
* best reference is <a href="http://www.yaml.org/spec/1.1/#id862121">
* 3.2.1.3. Nodes Comparison</a> where it hints that a duplicate map key is
* an error.
*
* For future reference, YAML spec 1.2 is clear. The keys MUST be unique.
* <a href="http://www.yaml.org/spec/1.2/spec.html#id2759572">1.3. Relation
* to JSON</a>
* @param allowDuplicateKeys false to reject duplicate mapping keys
*/
public void setAllowDuplicateKeys(boolean allowDuplicateKeys) {
this.allowDuplicateKeys = allowDuplicateKeys;
}
}

View File

@ -1,148 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml;
import java.util.HashMap;
import java.util.Map;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Provides additional runtime information necessary to create a custom Java
* instance.
*/
public final class TypeDescription {
private final Class<? extends Object> type;
private Tag tag;
private Map<String, Class<? extends Object>> listProperties;
private Map<String, Class<? extends Object>> keyProperties;
private Map<String, Class<? extends Object>> valueProperties;
public TypeDescription(Class<? extends Object> clazz, Tag tag) {
this.type = clazz;
this.tag = tag;
listProperties = new HashMap<String, Class<? extends Object>>();
keyProperties = new HashMap<String, Class<? extends Object>>();
valueProperties = new HashMap<String, Class<? extends Object>>();
}
public TypeDescription(Class<? extends Object> clazz, String tag) {
this(clazz, new Tag(tag));
}
public TypeDescription(Class<? extends Object> clazz) {
this(clazz, (Tag) null);
}
/**
* Get tag which shall be used to load or dump the type (class).
*
* @return tag to be used. It may be a tag for Language-Independent Types
* (http://www.yaml.org/type/)
*/
public Tag getTag() {
return tag;
}
/**
* Set tag to be used to load or dump the type (class).
*
* @param tag
* local or global tag
*/
public void setTag(Tag tag) {
this.tag = tag;
}
public void setTag(String tag) {
setTag(new Tag(tag));
}
/**
* Get represented type (class)
*
* @return type (class) to be described.
*/
public Class<? extends Object> getType() {
return type;
}
/**
* Specify that the property is a type-safe <code>List</code>.
*
* @param property
* name of the JavaBean property
* @param type
* class of List values
*/
public void putListPropertyType(String property, Class<? extends Object> type) {
listProperties.put(property, type);
}
/**
* Get class of List values for provided JavaBean property.
*
* @param property
* property name
* @return class of List values
*/
public Class<? extends Object> getListPropertyType(String property) {
return listProperties.get(property);
}
/**
* Specify that the property is a type-safe <code>Map</code>.
*
* @param property
* property name of this JavaBean
* @param key
* class of keys in Map
* @param value
* class of values in Map
*/
public void putMapPropertyType(String property, Class<? extends Object> key,
Class<? extends Object> value) {
keyProperties.put(property, key);
valueProperties.put(property, value);
}
/**
* Get keys type info for this JavaBean
*
* @param property
* property name of this JavaBean
* @return class of keys in the Map
*/
public Class<? extends Object> getMapKeyType(String property) {
return keyProperties.get(property);
}
/**
* Get values type info for this JavaBean
*
* @param property
* property name of this JavaBean
* @return class of values in the Map
*/
public Class<? extends Object> getMapValueType(String property) {
return valueProperties.get(property);
}
@Override
public String toString() {
return "TypeDescription for " + getType() + " (tag='" + getTag() + "')";
}
}

View File

@ -1,716 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.composer.Composer;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.emitter.Emitable;
import org.yaml.snakeyaml.emitter.Emitter;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.events.Event;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.parser.Parser;
import org.yaml.snakeyaml.parser.ParserImpl;
import org.yaml.snakeyaml.reader.StreamReader;
import org.yaml.snakeyaml.reader.UnicodeReader;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;
import org.yaml.snakeyaml.serializer.Serializer;
/**
* Public YAML interface. Each Thread must have its own instance.
*/
public class Yaml {
protected final Resolver resolver;
private String name;
protected BaseConstructor constructor;
protected Representer representer;
protected DumperOptions dumperOptions;
protected LoaderOptions loadingConfig;
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*/
public Yaml() {
this(new Constructor(), new Representer(), new DumperOptions(), new LoaderOptions(),
new Resolver());
}
/**
* Create Yaml instance.
*
* @param dumperOptions
* DumperOptions to configure outgoing objects
*/
public Yaml(DumperOptions dumperOptions) {
this(new Constructor(), new Representer(), dumperOptions);
}
/**
* Create Yaml instance.
*
* @param loadingConfig
* LoadingConfig to control load behavior
*/
public Yaml(LoaderOptions loadingConfig) {
this(new Constructor(), new Representer(), new DumperOptions(), loadingConfig);
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param representer
* Representer to emit outgoing objects
*/
public Yaml(Representer representer) {
this(new Constructor(), representer);
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param constructor
* BaseConstructor to construct incoming documents
*/
public Yaml(BaseConstructor constructor) {
this(constructor, new Representer());
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param constructor
* BaseConstructor to construct incoming documents
* @param representer
* Representer to emit outgoing objects
*/
public Yaml(BaseConstructor constructor, Representer representer) {
this(constructor, representer, new DumperOptions());
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param representer
* Representer to emit outgoing objects
* @param dumperOptions
* DumperOptions to configure outgoing objects
*/
public Yaml(Representer representer, DumperOptions dumperOptions) {
this(new Constructor(), representer, dumperOptions, new LoaderOptions(), new Resolver());
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param constructor
* BaseConstructor to construct incoming documents
* @param representer
* Representer to emit outgoing objects
* @param dumperOptions
* DumperOptions to configure outgoing objects
*/
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions) {
this(constructor, representer, dumperOptions, new LoaderOptions(), new Resolver());
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param constructor
* BaseConstructor to construct incoming documents
* @param representer
* Representer to emit outgoing objects
* @param dumperOptions
* DumperOptions to configure outgoing objects
* @param loadingConfig
* LoadingConfig to control load behavior
*/
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
LoaderOptions loadingConfig) {
this(constructor, representer, dumperOptions, loadingConfig, new Resolver());
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param constructor
* BaseConstructor to construct incoming documents
* @param representer
* Representer to emit outgoing objects
* @param dumperOptions
* DumperOptions to configure outgoing objects
* @param resolver
* Resolver to detect implicit type
*/
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
Resolver resolver) {
this(constructor, representer, dumperOptions, new LoaderOptions(), resolver);
}
/**
* Create Yaml instance. It is safe to create a few instances and use them
* in different Threads.
*
* @param constructor
* BaseConstructor to construct incoming documents
* @param representer
* Representer to emit outgoing objects
* @param dumperOptions
* DumperOptions to configure outgoing objects
* @param loadingConfig
* LoadingConfig to control load behavior
* @param resolver
* Resolver to detect implicit type
*/
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
LoaderOptions loadingConfig, Resolver resolver) {
if (!constructor.isExplicitPropertyUtils()) {
constructor.setPropertyUtils(representer.getPropertyUtils());
} else if (!representer.isExplicitPropertyUtils()) {
representer.setPropertyUtils(constructor.getPropertyUtils());
}
this.constructor = constructor;
this.constructor.setAllowDuplicateKeys(loadingConfig.isAllowDuplicateKeys());
if (dumperOptions.getIndent() <= dumperOptions.getIndicatorIndent()) {
throw new YAMLException("Indicator indent must be smaller then indent.");
}
representer.setDefaultFlowStyle(dumperOptions.getDefaultFlowStyle());
representer.setDefaultScalarStyle(dumperOptions.getDefaultScalarStyle());
representer.getPropertyUtils()
.setAllowReadOnlyProperties(dumperOptions.isAllowReadOnlyProperties());
representer.setTimeZone(dumperOptions.getTimeZone());
this.representer = representer;
this.dumperOptions = dumperOptions;
this.loadingConfig = loadingConfig;
this.resolver = resolver;
this.name = "Yaml:" + System.identityHashCode(this);
}
/**
* Serialize a Java object into a YAML String.
*
* @param data
* Java object to be Serialized to YAML
* @return YAML String
*/
public String dump(Object data) {
List<Object> list = new ArrayList<Object>(1);
list.add(data);
return dumpAll(list.iterator());
}
/**
* Produce the corresponding representation tree for a given Object.
*
* @see <a href="http://yaml.org/spec/1.1/#id859333">Figure 3.1. Processing
* Overview</a>
* @param data
* instance to build the representation tree for
* @return representation tree
*/
public Node represent(Object data) {
return representer.represent(data);
}
/**
* Serialize a sequence of Java objects into a YAML String.
*
* @param data
* Iterator with Objects
* @return YAML String with all the objects in proper sequence
*/
public String dumpAll(Iterator<? extends Object> data) {
StringWriter buffer = new StringWriter();
dumpAll(data, buffer, null);
return buffer.toString();
}
/**
* Serialize a Java object into a YAML stream.
*
* @param data
* Java object to be serialized to YAML
* @param output
* stream to write to
*/
public void dump(Object data, Writer output) {
List<Object> list = new ArrayList<Object>(1);
list.add(data);
dumpAll(list.iterator(), output, null);
}
/**
* Serialize a sequence of Java objects into a YAML stream.
*
* @param data
* Iterator with Objects
* @param output
* stream to write to
*/
public void dumpAll(Iterator<? extends Object> data, Writer output) {
dumpAll(data, output, null);
}
private void dumpAll(Iterator<? extends Object> data, Writer output, Tag rootTag) {
Serializer serializer = new Serializer(new Emitter(output, dumperOptions), resolver,
dumperOptions, rootTag);
try {
serializer.open();
while (data.hasNext()) {
Node node = representer.represent(data.next());
serializer.serialize(node);
}
serializer.close();
} catch (IOException e) {
throw new YAMLException(e);
}
}
/**
* <p>
* Serialize a Java object into a YAML string. Override the default root tag
* with <code>rootTag</code>.
* </p>
*
* <p>
* This method is similar to <code>Yaml.dump(data)</code> except that the
* root tag for the whole document is replaced with the given tag. This has
* two main uses.
* </p>
*
* <p>
* First, if the root tag is replaced with a standard YAML tag, such as
* <code>Tag.MAP</code>, then the object will be dumped as a map. The root
* tag will appear as <code>!!map</code>, or blank (implicit !!map).
* </p>
*
* <p>
* Second, if the root tag is replaced by a different custom tag, then the
* document appears to be a different type when loaded. For example, if an
* instance of MyClass is dumped with the tag !!YourClass, then it will be
* handled as an instance of YourClass when loaded.
* </p>
*
* @param data
* Java object to be serialized to YAML
* @param rootTag
* the tag for the whole YAML document. The tag should be Tag.MAP
* for a JavaBean to make the tag disappear (to use implicit tag
* !!map). If <code>null</code> is provided then the standard tag
* with the full class name is used.
* @param flowStyle
* flow style for the whole document. See Chapter 10. Collection
* Styles http://yaml.org/spec/1.1/#id930798. If
* <code>null</code> is provided then the flow style from
* DumperOptions is used.
*
* @return YAML String
*/
public String dumpAs(Object data, Tag rootTag, FlowStyle flowStyle) {
FlowStyle oldStyle = representer.getDefaultFlowStyle();
if (flowStyle != null) {
representer.setDefaultFlowStyle(flowStyle);
}
List<Object> list = new ArrayList<Object>(1);
list.add(data);
StringWriter buffer = new StringWriter();
dumpAll(list.iterator(), buffer, rootTag);
representer.setDefaultFlowStyle(oldStyle);
return buffer.toString();
}
/**
* <p>
* Serialize a Java object into a YAML string. Override the default root tag
* with <code>Tag.MAP</code>.
* </p>
* <p>
* This method is similar to <code>Yaml.dump(data)</code> except that the
* root tag for the whole document is replaced with <code>Tag.MAP</code> tag
* (implicit !!map).
* </p>
* <p>
* Block Mapping is used as the collection style. See 10.2.2. Block Mappings
* (http://yaml.org/spec/1.1/#id934537)
* </p>
*
* @param data
* Java object to be serialized to YAML
* @return YAML String
*/
public String dumpAsMap(Object data) {
return dumpAs(data, Tag.MAP, FlowStyle.BLOCK);
}
/**
* Serialize the representation tree into Events.
*
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
* @param data
* representation tree
* @return Event list
*/
public List<Event> serialize(Node data) {
SilentEmitter emitter = new SilentEmitter();
Serializer serializer = new Serializer(emitter, resolver, dumperOptions, null);
try {
serializer.open();
serializer.serialize(data);
serializer.close();
} catch (IOException e) {
throw new YAMLException(e);
}
return emitter.getEvents();
}
private static class SilentEmitter implements Emitable {
private List<Event> events = new ArrayList<Event>(100);
public List<Event> getEvents() {
return events;
}
public void emit(Event event) throws IOException {
events.add(event);
}
}
/**
* Parse the only YAML document in a String and produce the corresponding
* Java object. (Because the encoding in known BOM is not respected.)
*
* @param yaml
* YAML data to load from (BOM must not be present)
* @return parsed object
*/
public Object load(String yaml) {
return loadFromReader(new StreamReader(yaml), Object.class);
}
/**
* Parse the only YAML document in a stream and produce the corresponding
* Java object.
*
* @param io
* data to load from (BOM is respected and removed)
* @return parsed object
*/
public Object load(InputStream io) {
return loadFromReader(new StreamReader(new UnicodeReader(io)), Object.class);
}
/**
* Parse the only YAML document in a stream and produce the corresponding
* Java object.
*
* @param io
* data to load from (BOM must not be present)
* @return parsed object
*/
public Object load(Reader io) {
return loadFromReader(new StreamReader(io), Object.class);
}
/**
* Parse the only YAML document in a stream and produce the corresponding
* Java object.
*
* @param <T>
* Class is defined by the second argument
* @param io
* data to load from (BOM must not be present)
* @param type
* Class of the object to be created
* @return parsed object
*/
@SuppressWarnings("unchecked")
public <T> T loadAs(Reader io, Class<T> type) {
return (T) loadFromReader(new StreamReader(io), type);
}
/**
* Parse the only YAML document in a String and produce the corresponding
* Java object. (Because the encoding in known BOM is not respected.)
*
* @param <T>
* Class is defined by the second argument
* @param yaml
* YAML data to load from (BOM must not be present)
* @param type
* Class of the object to be created
* @return parsed object
*/
@SuppressWarnings("unchecked")
public <T> T loadAs(String yaml, Class<T> type) {
return (T) loadFromReader(new StreamReader(yaml), type);
}
/**
* Parse the only YAML document in a stream and produce the corresponding
* Java object.
*
* @param <T>
* Class is defined by the second argument
* @param input
* data to load from (BOM is respected and removed)
* @param type
* Class of the object to be created
* @return parsed object
*/
@SuppressWarnings("unchecked")
public <T> T loadAs(InputStream input, Class<T> type) {
return (T) loadFromReader(new StreamReader(new UnicodeReader(input)), type);
}
private Object loadFromReader(StreamReader sreader, Class<?> type) {
Composer composer = new Composer(new ParserImpl(sreader), resolver);
constructor.setComposer(composer);
return constructor.getSingleData(type);
}
/**
* Parse all YAML documents in a String and produce corresponding Java
* objects. The documents are parsed only when the iterator is invoked.
*
* @param yaml
* YAML data to load from (BOM must not be present)
* @return an iterator over the parsed Java objects in this String in proper
* sequence
*/
public Iterable<Object> loadAll(Reader yaml) {
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
constructor.setComposer(composer);
Iterator<Object> result = new Iterator<Object>() {
public boolean hasNext() {
return constructor.checkData();
}
public Object next() {
return constructor.getData();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return new YamlIterable(result);
}
private static class YamlIterable implements Iterable<Object> {
private Iterator<Object> iterator;
public YamlIterable(Iterator<Object> iterator) {
this.iterator = iterator;
}
public Iterator<Object> iterator() {
return iterator;
}
}
/**
* Parse all YAML documents in a String and produce corresponding Java
* objects. (Because the encoding in known BOM is not respected.) The
* documents are parsed only when the iterator is invoked.
*
* @param yaml
* YAML data to load from (BOM must not be present)
* @return an iterator over the parsed Java objects in this String in proper
* sequence
*/
public Iterable<Object> loadAll(String yaml) {
return loadAll(new StringReader(yaml));
}
/**
* Parse all YAML documents in a stream and produce corresponding Java
* objects. The documents are parsed only when the iterator is invoked.
*
* @param yaml
* YAML data to load from (BOM is respected and ignored)
* @return an iterator over the parsed Java objects in this stream in proper
* sequence
*/
public Iterable<Object> loadAll(InputStream yaml) {
return loadAll(new UnicodeReader(yaml));
}
/**
* Parse the first YAML document in a stream and produce the corresponding
* representation tree. (This is the opposite of the represent() method)
*
* @see <a href="http://yaml.org/spec/1.1/#id859333">Figure 3.1. Processing
* Overview</a>
* @param yaml
* YAML document
* @return parsed root Node for the specified YAML document
*/
public Node compose(Reader yaml) {
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
constructor.setComposer(composer);
return composer.getSingleNode();
}
/**
* Parse all YAML documents in a stream and produce corresponding
* representation trees.
*
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
* @param yaml
* stream of YAML documents
* @return parsed root Nodes for all the specified YAML documents
*/
public Iterable<Node> composeAll(Reader yaml) {
final Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
constructor.setComposer(composer);
Iterator<Node> result = new Iterator<Node>() {
public boolean hasNext() {
return composer.checkNode();
}
public Node next() {
return composer.getNode();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return new NodeIterable(result);
}
private static class NodeIterable implements Iterable<Node> {
private Iterator<Node> iterator;
public NodeIterable(Iterator<Node> iterator) {
this.iterator = iterator;
}
public Iterator<Node> iterator() {
return iterator;
}
}
/**
* Add an implicit scalar detector. If an implicit scalar value matches the
* given regexp, the corresponding tag is assigned to the scalar.
*
* @param tag
* tag to assign to the node
* @param regexp
* regular expression to match against
* @param first
* a sequence of possible initial characters or null (which means
* any).
*/
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
resolver.addImplicitResolver(tag, regexp, first);
}
@Override
public String toString() {
return name;
}
/**
* Get a meaningful name. It simplifies debugging in a multi-threaded
* environment. If nothing is set explicitly the address of the instance is
* returned.
*
* @return human readable name
*/
public String getName() {
return name;
}
/**
* Set a meaningful name to be shown in toString()
*
* @param name
* human readable name
*/
public void setName(String name) {
this.name = name;
}
/**
* Parse a YAML stream and produce parsing events.
*
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
* @param yaml
* YAML document(s)
* @return parsed events
*/
public Iterable<Event> parse(Reader yaml) {
final Parser parser = new ParserImpl(new StreamReader(yaml));
Iterator<Event> result = new Iterator<Event>() {
public boolean hasNext() {
return parser.peekEvent() != null;
}
public Event next() {
return parser.getEvent();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return new EventIterable(result);
}
private static class EventIterable implements Iterable<Event> {
private Iterator<Event> iterator;
public EventIterable(Iterator<Event> iterator) {
this.iterator = iterator;
}
public Iterator<Event> iterator() {
return iterator;
}
}
public void setBeanAccess(BeanAccess beanAccess) {
constructor.getPropertyUtils().setBeanAccess(beanAccess);
representer.getPropertyUtils().setBeanAccess(beanAccess);
}
}

View File

@ -1,248 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.composer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.yaml.snakeyaml.events.AliasEvent;
import org.yaml.snakeyaml.events.Event;
import org.yaml.snakeyaml.events.MappingStartEvent;
import org.yaml.snakeyaml.events.NodeEvent;
import org.yaml.snakeyaml.events.ScalarEvent;
import org.yaml.snakeyaml.events.SequenceStartEvent;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.parser.Parser;
import org.yaml.snakeyaml.resolver.Resolver;
/**
* Creates a node graph from parser events.
* <p>
* Corresponds to the 'Compose' step as described in chapter 3.1 of the
* <a href="http://yaml.org/spec/1.1/">YAML Specification</a>.
* </p>
*/
public class Composer {
protected final Parser parser;
private final Resolver resolver;
private final Map<String, Node> anchors;
private final Set<Node> recursiveNodes;
public Composer(Parser parser, Resolver resolver) {
this.parser = parser;
this.resolver = resolver;
this.anchors = new HashMap<String, Node>();
this.recursiveNodes = new HashSet<Node>();
}
/**
* Checks if further documents are available.
*
* @return <code>true</code> if there is at least one more document.
*/
public boolean checkNode() {
// Drop the STREAM-START event.
if (parser.checkEvent(Event.ID.StreamStart)) {
parser.getEvent();
}
// If there are more documents available?
return !parser.checkEvent(Event.ID.StreamEnd);
}
/**
* Reads and composes the next document.
*
* @return The root node of the document or <code>null</code> if no more
* documents are available.
*/
public Node getNode() {
// Get the root node of the next document.
if (!parser.checkEvent(Event.ID.StreamEnd)) {
return composeDocument();
} else {
return null;
}
}
/**
* Reads a document from a source that contains only one document.
* <p>
* If the stream contains more than one document an exception is thrown.
* </p>
*
* @return The root node of the document or <code>null</code> if no document
* is available.
*/
public Node getSingleNode() {
// Drop the STREAM-START event.
parser.getEvent();
// Compose a document if the stream is not empty.
Node document = null;
if (!parser.checkEvent(Event.ID.StreamEnd)) {
document = composeDocument();
}
// Ensure that the stream contains no more documents.
if (!parser.checkEvent(Event.ID.StreamEnd)) {
Event event = parser.getEvent();
throw new ComposerException("expected a single document in the stream",
document.getStartMark(), "but found another document", event.getStartMark());
}
// Drop the STREAM-END event.
parser.getEvent();
return document;
}
private Node composeDocument() {
// Drop the DOCUMENT-START event.
parser.getEvent();
// Compose the root node.
Node node = composeNode(null);
// Drop the DOCUMENT-END event.
parser.getEvent();
this.anchors.clear();
recursiveNodes.clear();
return node;
}
private Node composeNode(Node parent) {
recursiveNodes.add(parent);
Node node = null;
if (parser.checkEvent(Event.ID.Alias)) {
AliasEvent event = (AliasEvent) parser.getEvent();
String anchor = event.getAnchor();
if (!anchors.containsKey(anchor)) {
throw new ComposerException(null, null, "found undefined alias " + anchor,
event.getStartMark());
}
node = anchors.get(anchor);
if (recursiveNodes.remove(node)) {
node.setTwoStepsConstruction(true);
}
} else {
NodeEvent event = (NodeEvent) parser.peekEvent();
String anchor = null;
anchor = event.getAnchor();
// the check for duplicate anchors has been removed (issue 174)
if (parser.checkEvent(Event.ID.Scalar)) {
node = composeScalarNode(anchor);
} else if (parser.checkEvent(Event.ID.SequenceStart)) {
node = composeSequenceNode(anchor);
} else {
node = composeMappingNode(anchor);
}
}
recursiveNodes.remove(parent);
return node;
}
protected Node composeScalarNode(String anchor) {
ScalarEvent ev = (ScalarEvent) parser.getEvent();
String tag = ev.getTag();
boolean resolved = false;
Tag nodeTag;
if (tag == null || tag.equals("!")) {
nodeTag = resolver.resolve(NodeId.scalar, ev.getValue(),
ev.getImplicit().canOmitTagInPlainScalar());
resolved = true;
} else {
nodeTag = new Tag(tag);
}
Node node = new ScalarNode(nodeTag, resolved, ev.getValue(), ev.getStartMark(),
ev.getEndMark(), ev.getStyle());
if (anchor != null) {
anchors.put(anchor, node);
}
return node;
}
protected Node composeSequenceNode(String anchor) {
SequenceStartEvent startEvent = (SequenceStartEvent) parser.getEvent();
String tag = startEvent.getTag();
Tag nodeTag;
boolean resolved = false;
if (tag == null || tag.equals("!")) {
nodeTag = resolver.resolve(NodeId.sequence, null, startEvent.getImplicit());
resolved = true;
} else {
nodeTag = new Tag(tag);
}
final ArrayList<Node> children = new ArrayList<Node>();
SequenceNode node = new SequenceNode(nodeTag, resolved, children, startEvent.getStartMark(),
null, startEvent.getFlowStyle());
if (anchor != null) {
anchors.put(anchor, node);
}
while (!parser.checkEvent(Event.ID.SequenceEnd)) {
children.add(composeNode(node));
}
Event endEvent = parser.getEvent();
node.setEndMark(endEvent.getEndMark());
return node;
}
protected Node composeMappingNode(String anchor) {
MappingStartEvent startEvent = (MappingStartEvent) parser.getEvent();
String tag = startEvent.getTag();
Tag nodeTag;
boolean resolved = false;
if (tag == null || tag.equals("!")) {
nodeTag = resolver.resolve(NodeId.mapping, null, startEvent.getImplicit());
resolved = true;
} else {
nodeTag = new Tag(tag);
}
final List<NodeTuple> children = new ArrayList<NodeTuple>();
MappingNode node = new MappingNode(nodeTag, resolved, children, startEvent.getStartMark(),
null, startEvent.getFlowStyle());
if (anchor != null) {
anchors.put(anchor, node);
}
while (!parser.checkEvent(Event.ID.MappingEnd)) {
composeMappingChildren(children, node);
}
Event endEvent = parser.getEvent();
node.setEndMark(endEvent.getEndMark());
return node;
}
protected void composeMappingChildren(List<NodeTuple> children, MappingNode node) {
Node itemKey = composeKeyNode(node);
if (itemKey.getTag().equals(Tag.MERGE)) {
node.setMerged(true);
}
Node itemValue = composeValueNode(node);
children.add(new NodeTuple(itemKey, itemValue));
}
protected Node composeKeyNode(MappingNode node) {
return composeNode(node);
}
protected Node composeValueNode(MappingNode node) {
return composeNode(node);
}
}

View File

@ -1,27 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.composer;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.error.MarkedYAMLException;
public class ComposerException extends MarkedYAMLException {
private static final long serialVersionUID = 2146314636913113935L;
protected ComposerException(String context, Mark contextMark, String problem, Mark problemMark) {
super(context, contextMark, problem, problemMark);
}
}

View File

@ -1,41 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.nodes.Node;
/**
* Because recursive structures are not very common we provide a way to save
* some typing when extending a constructor
*/
public abstract class AbstractConstruct implements Construct {
/**
* Fail with a reminder to provide the seconds step for a recursive
* structure
*
* @see org.yaml.snakeyaml.constructor.Construct#construct2ndStep(org.yaml.snakeyaml.nodes.Node,
* java.lang.Object)
*/
public void construct2ndStep(Node node, Object data) {
if (node.isTwoStepsConstruction()) {
throw new IllegalStateException("Not Implemented in " + getClass().getName());
} else {
throw new YAMLException("Unexpected recursive structure for Node: " + node);
}
}
}

View File

@ -1,461 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.yaml.snakeyaml.composer.Composer;
import org.yaml.snakeyaml.composer.ComposerException;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.introspector.PropertyUtils;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
public abstract class BaseConstructor {
/**
* It maps the node kind to the the Construct implementation. When the
* runtime class is known then the implicit tag is ignored.
*/
protected final Map<NodeId, Construct> yamlClassConstructors = new EnumMap<NodeId, Construct>(
NodeId.class);
/**
* It maps the (explicit or implicit) tag to the Construct implementation.
* It is used:
* 1) explicit tag - if present.
* 2) implicit tag - when the runtime class of the instance is unknown (the
* node has the Object.class)
*/
protected final Map<Tag, Construct> yamlConstructors = new HashMap<Tag, Construct>();
/**
* It maps the (explicit or implicit) tag to the Construct implementation.
* It is used when no exact match found.
*/
protected final Map<String, Construct> yamlMultiConstructors = new HashMap<String, Construct>();
protected Composer composer;
private final Map<Node, Object> constructedObjects;
private final Set<Node> recursiveObjects;
private final ArrayList<RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>>> maps2fill;
private final ArrayList<RecursiveTuple<Set<Object>, Object>> sets2fill;
protected Tag rootTag;
private PropertyUtils propertyUtils;
private boolean explicitPropertyUtils;
private boolean allowDuplicateKeys = true;
public BaseConstructor() {
constructedObjects = new HashMap<Node, Object>();
recursiveObjects = new HashSet<Node>();
maps2fill = new ArrayList<RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>>>();
sets2fill = new ArrayList<RecursiveTuple<Set<Object>, Object>>();
rootTag = null;
explicitPropertyUtils = false;
}
public void setComposer(Composer composer) {
this.composer = composer;
}
/**
* Check if more documents available
*
* @return true when there are more YAML documents in the stream
*/
public boolean checkData() {
// If there are more documents available?
return composer.checkNode();
}
/**
* Construct and return the next document
*
* @return constructed instance
*/
public Object getData() {
// Construct and return the next document.
composer.checkNode();
Node node = composer.getNode();
if (rootTag != null) {
node.setTag(rootTag);
}
return constructDocument(node);
}
/**
* Ensure that the stream contains a single document and construct it
*
* @param type the class of the instance being created
* @return constructed instance
* @throws ComposerException
* in case there are more documents in the stream
*/
public Object getSingleData(Class<?> type) {
// Ensure that the stream contains a single document and construct it
Node node = composer.getSingleNode();
if (node != null) {
if (Object.class != type) {
node.setTag(new Tag(type));
} else if (rootTag != null) {
node.setTag(rootTag);
}
return constructDocument(node);
}
return null;
}
/**
* Construct complete YAML document. Call the second step in case of
* recursive structures. At the end cleans all the state.
*
* @param node
* root Node
* @return Java instance
*/
protected final Object constructDocument(Node node) {
Object data = constructObject(node);
fillRecursive();
constructedObjects.clear();
recursiveObjects.clear();
return data;
}
private void fillRecursive() {
if (!maps2fill.isEmpty()) {
for (RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>> entry : maps2fill) {
RecursiveTuple<Object, Object> key_value = entry._2();
entry._1().put(key_value._1(), key_value._2());
}
maps2fill.clear();
}
if (!sets2fill.isEmpty()) {
for (RecursiveTuple<Set<Object>, Object> value : sets2fill) {
value._1().add(value._2());
}
sets2fill.clear();
}
}
/**
* Construct object from the specified Node. Return existing instance if the
* node is already constructed.
*
* @param node
* Node to be constructed
* @return Java instance
*/
protected Object constructObject(Node node) {
if (constructedObjects.containsKey(node)) {
return constructedObjects.get(node);
}
if (recursiveObjects.contains(node)) {
throw new ConstructorException(null, null, "found unconstructable recursive node",
node.getStartMark());
}
recursiveObjects.add(node);
Construct constructor = getConstructor(node);
Object data = constructor.construct(node);
constructedObjects.put(node, data);
recursiveObjects.remove(node);
if (node.isTwoStepsConstruction()) {
constructor.construct2ndStep(node, data);
}
return data;
}
/**
* Get the constructor to construct the Node. For implicit tags if the
* runtime class is known a dedicated Construct implementation is used.
* Otherwise the constructor is chosen by the tag.
*
* @param node
* Node to be constructed
* @return Construct implementation for the specified node
*/
protected Construct getConstructor(Node node) {
if (node.useClassConstructor()) {
return yamlClassConstructors.get(node.getNodeId());
} else {
Construct constructor = yamlConstructors.get(node.getTag());
if (constructor == null) {
for (String prefix : yamlMultiConstructors.keySet()) {
if (node.getTag().startsWith(prefix)) {
return yamlMultiConstructors.get(prefix);
}
}
return yamlConstructors.get(null);
}
return constructor;
}
}
protected Object constructScalar(ScalarNode node) {
return node.getValue();
}
protected List<Object> createDefaultList(int initSize) {
return new ArrayList<Object>(initSize);
}
protected Set<Object> createDefaultSet(int initSize) {
return new LinkedHashSet<Object>(initSize);
}
protected Object createArray(Class<?> type, int size) {
return Array.newInstance(type.getComponentType(), size);
}
@SuppressWarnings("unchecked")
protected List<? extends Object> constructSequence(SequenceNode node) {
List<Object> result;
if (List.class.isAssignableFrom(node.getType()) && !node.getType().isInterface()) {
// the root class may be defined (Vector for instance)
try {
result = (List<Object>) node.getType().newInstance();
} catch (Exception e) {
throw new YAMLException(e);
}
} else {
result = createDefaultList(node.getValue().size());
}
constructSequenceStep2(node, result);
return result;
}
@SuppressWarnings("unchecked")
protected Set<? extends Object> constructSet(SequenceNode node) {
Set<Object> result;
if (!node.getType().isInterface()) {
// the root class may be defined
try {
result = (Set<Object>) node.getType().newInstance();
} catch (Exception e) {
throw new YAMLException(e);
}
} else {
result = createDefaultSet(node.getValue().size());
}
constructSequenceStep2(node, result);
return result;
}
protected Object constructArray(SequenceNode node) {
return constructArrayStep2(node, createArray(node.getType(), node.getValue().size()));
}
protected void constructSequenceStep2(SequenceNode node, Collection<Object> collection) {
for (Node child : node.getValue()) {
collection.add(constructObject(child));
}
}
protected Object constructArrayStep2(SequenceNode node, Object array) {
final Class<?> componentType = node.getType().getComponentType();
int index = 0;
for (Node child : node.getValue()) {
// Handle multi-dimensional arrays...
if (child.getType() == Object.class) {
child.setType(componentType);
}
final Object value = constructObject(child);
if (componentType.isPrimitive()) {
// Null values are disallowed for primitives
if (value == null) {
throw new NullPointerException(
"Unable to construct element value for " + child);
}
// Primitive arrays require quite a lot of work.
if (byte.class.equals(componentType)) {
Array.setByte(array, index, ((Number) value).byteValue());
} else if (short.class.equals(componentType)) {
Array.setShort(array, index, ((Number) value).shortValue());
} else if (int.class.equals(componentType)) {
Array.setInt(array, index, ((Number) value).intValue());
} else if (long.class.equals(componentType)) {
Array.setLong(array, index, ((Number) value).longValue());
} else if (float.class.equals(componentType)) {
Array.setFloat(array, index, ((Number) value).floatValue());
} else if (double.class.equals(componentType)) {
Array.setDouble(array, index, ((Number) value).doubleValue());
} else if (char.class.equals(componentType)) {
Array.setChar(array, index, ((Character) value).charValue());
} else if (boolean.class.equals(componentType)) {
Array.setBoolean(array, index, ((Boolean) value).booleanValue());
} else {
throw new YAMLException("unexpected primitive type");
}
} else {
// Non-primitive arrays can simply be assigned:
Array.set(array, index, value);
}
++index;
}
return array;
}
protected Map<Object, Object> createDefaultMap() {
// respect order from YAML document
return new LinkedHashMap<Object, Object>();
}
protected Set<Object> createDefaultSet() {
// respect order from YAML document
return new LinkedHashSet<Object>();
}
protected Set<Object> constructSet(MappingNode node) {
Set<Object> set = createDefaultSet();
constructSet2ndStep(node, set);
return set;
}
protected Map<Object, Object> constructMapping(MappingNode node) {
Map<Object, Object> mapping = createDefaultMap();
constructMapping2ndStep(node, mapping);
return mapping;
}
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
List<NodeTuple> nodeValue = node.getValue();
for (NodeTuple tuple : nodeValue) {
Node keyNode = tuple.getKeyNode();
Node valueNode = tuple.getValueNode();
Object key = constructObject(keyNode);
if (key != null) {
try {
key.hashCode();// check circular dependencies
} catch (Exception e) {
throw new ConstructorException("while constructing a mapping",
node.getStartMark(), "found unacceptable key " + key,
tuple.getKeyNode().getStartMark(), e);
}
}
Object value = constructObject(valueNode);
if (keyNode.isTwoStepsConstruction()) {
/*
* if keyObject is created it 2 steps we should postpone putting
* it in map because it may have different hash after
* initialization compared to clean just created one. And map of
* course does not observe key hashCode changes.
*/
maps2fill.add(0,
new RecursiveTuple<Map<Object, Object>, RecursiveTuple<Object, Object>>(
mapping, new RecursiveTuple<Object, Object>(key, value)));
} else {
mapping.put(key, value);
}
}
}
protected void constructSet2ndStep(MappingNode node, Set<Object> set) {
List<NodeTuple> nodeValue = node.getValue();
for (NodeTuple tuple : nodeValue) {
Node keyNode = tuple.getKeyNode();
Object key = constructObject(keyNode);
if (key != null) {
try {
key.hashCode();// check circular dependencies
} catch (Exception e) {
throw new ConstructorException("while constructing a Set", node.getStartMark(),
"found unacceptable key " + key, tuple.getKeyNode().getStartMark(), e);
}
}
if (keyNode.isTwoStepsConstruction()) {
/*
* if keyObject is created it 2 steps we should postpone putting
* it into the set because it may have different hash after
* initialization compared to clean just created one. And set of
* course does not observe value hashCode changes.
*/
sets2fill.add(0, new RecursiveTuple<Set<Object>, Object>(set, key));
} else {
set.add(key);
}
}
}
public void setPropertyUtils(PropertyUtils propertyUtils) {
this.propertyUtils = propertyUtils;
explicitPropertyUtils = true;
}
public final PropertyUtils getPropertyUtils() {
if (propertyUtils == null) {
propertyUtils = new PropertyUtils();
}
return propertyUtils;
}
private static class RecursiveTuple<T, K> {
private final T _1;
private final K _2;
public RecursiveTuple(T _1, K _2) {
this._1 = _1;
this._2 = _2;
}
public K _2() {
return _2;
}
public T _1() {
return _1;
}
}
public final boolean isExplicitPropertyUtils() {
return explicitPropertyUtils;
}
public boolean isAllowDuplicateKeys() {
return allowDuplicateKeys;
}
public void setAllowDuplicateKeys(boolean allowDuplicateKeys) {
this.allowDuplicateKeys = allowDuplicateKeys;
}
}

View File

@ -1,50 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
import org.yaml.snakeyaml.nodes.Node;
/**
* Provide a way to construct a Java instance out of the composed Node. Support
* recursive objects if it is required. (create Native Data Structure out of
* Node Graph)
*
* @see <a href="http://yaml.org/spec/1.1/#id859109">Chapter 3. Processing YAML
* Information</a>
*/
public interface Construct {
/**
* Construct a Java instance with all the properties injected when it is
* possible.
*
* @param node
* composed Node
* @return a complete Java instance
*/
Object construct(Node node);
/**
* Apply the second step when constructing recursive structures. Because the
* instance is already created it can assign a reference to itself.
*
* @param node
* composed Node
* @param object
* the instance constructed earlier by
* <code>construct(Node node)</code> for the provided Node
*/
void construct2ndStep(Node node, Object object);
}

View File

@ -1,682 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
import java.beans.IntrospectionException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Construct a custom Java instance.
*/
public class Constructor extends SafeConstructor {
private final Map<Tag, Class<? extends Object>> typeTags;
protected final Map<Class<? extends Object>, TypeDescription> typeDefinitions;
public Constructor() {
this(Object.class);
}
/**
* Create Constructor for the specified class as the root.
*
* @param theRoot
* - the class (usually JavaBean) to be constructed
*/
public Constructor(Class<? extends Object> theRoot) {
this(new TypeDescription(checkRoot(theRoot)));
}
/**
* Ugly Java way to check the argument in the constructor
*/
private static Class<? extends Object> checkRoot(Class<? extends Object> theRoot) {
if (theRoot == null) {
throw new NullPointerException("Root class must be provided.");
} else
return theRoot;
}
public Constructor(TypeDescription theRoot) {
if (theRoot == null) {
throw new NullPointerException("Root type must be provided.");
}
this.yamlConstructors.put(null, new ConstructYamlObject());
if (!Object.class.equals(theRoot.getType())) {
rootTag = new Tag(theRoot.getType());
}
typeTags = new HashMap<Tag, Class<? extends Object>>();
typeDefinitions = new HashMap<Class<? extends Object>, TypeDescription>();
yamlClassConstructors.put(NodeId.scalar, new ConstructScalar());
yamlClassConstructors.put(NodeId.mapping, new ConstructMapping());
yamlClassConstructors.put(NodeId.sequence, new ConstructSequence());
addTypeDescription(theRoot);
}
/**
* Create Constructor for a class which does not have to be in the classpath
* or for a definition from a Spring ApplicationContext.
*
* @param theRoot
* fully qualified class name of the root class (usually
* JavaBean)
* @throws ClassNotFoundException if cannot be loaded by the classloader
*/
public Constructor(String theRoot) throws ClassNotFoundException {
this(Class.forName(check(theRoot)));
}
private static final String check(String s) {
if (s == null) {
throw new NullPointerException("Root type must be provided.");
}
if (s.trim().length() == 0) {
throw new YAMLException("Root type must be provided.");
}
return s;
}
/**
* Make YAML aware how to parse a custom Class. If there is no root Class
* assigned in constructor then the 'root' property of this definition is
* respected.
*
* @param definition
* to be added to the Constructor
* @return the previous value associated with <tt>definition</tt>, or
* <tt>null</tt> if there was no mapping for <tt>definition</tt>.
*/
public TypeDescription addTypeDescription(TypeDescription definition) {
if (definition == null) {
throw new NullPointerException("TypeDescription is required.");
}
Tag tag = definition.getTag();
typeTags.put(tag, definition.getType());
return typeDefinitions.put(definition.getType(), definition);
}
/**
* Construct mapping instance (Map, JavaBean) when the runtime class is
* known.
*/
protected class ConstructMapping implements Construct {
/**
* Construct JavaBean. If type safe collections are used please look at
* <code>TypeDescription</code>.
*
* @param node
* node where the keys are property names (they can only be
* <code>String</code>s) and values are objects to be created
* @return constructed JavaBean
*/
public Object construct(Node node) {
MappingNode mnode = (MappingNode) node;
if (Properties.class.isAssignableFrom(node.getType())) {
Properties properties = new Properties();
if (!node.isTwoStepsConstruction()) {
constructMapping2ndStep(mnode, properties);
} else {
throw new YAMLException("Properties must not be recursive.");
}
return properties;
} else if (SortedMap.class.isAssignableFrom(node.getType())) {
SortedMap<Object, Object> map = new TreeMap<Object, Object>();
if (!node.isTwoStepsConstruction()) {
constructMapping2ndStep(mnode, map);
}
return map;
} else if (Map.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
return createDefaultMap();
} else {
return constructMapping(mnode);
}
} else if (SortedSet.class.isAssignableFrom(node.getType())) {
SortedSet<Object> set = new TreeSet<Object>();
// XXX why this is not used ?
// if (!node.isTwoStepsConstruction()) {
constructSet2ndStep(mnode, set);
// }
return set;
} else if (Collection.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
return createDefaultSet();
} else {
return constructSet(mnode);
}
} else {
if (node.isTwoStepsConstruction()) {
return createEmptyJavaBean(mnode);
} else {
return constructJavaBean2ndStep(mnode, createEmptyJavaBean(mnode));
}
}
}
@SuppressWarnings("unchecked")
public void construct2ndStep(Node node, Object object) {
if (Map.class.isAssignableFrom(node.getType())) {
constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object);
} else if (Set.class.isAssignableFrom(node.getType())) {
constructSet2ndStep((MappingNode) node, (Set<Object>) object);
} else {
constructJavaBean2ndStep((MappingNode) node, object);
}
}
protected Object createEmptyJavaBean(MappingNode node) {
try {
/**
* Using only default constructor. Everything else will be
* initialized on 2nd step. If we do here some partial
* initialization, how do we then track what need to be done on
* 2nd step? I think it is better to get only object here (to
* have it as reference for recursion) and do all other thing on
* 2nd step.
*/
java.lang.reflect.Constructor<?> c = node.getType().getDeclaredConstructor();
c.setAccessible(true);
return c.newInstance();
} catch (Exception e) {
throw new YAMLException(e);
}
}
protected Object constructJavaBean2ndStep(MappingNode node, Object object) {
flattenMapping(node);
Class<? extends Object> beanType = node.getType();
List<NodeTuple> nodeValue = node.getValue();
for (NodeTuple tuple : nodeValue) {
ScalarNode keyNode;
if (tuple.getKeyNode() instanceof ScalarNode) {
// key must be scalar
keyNode = (ScalarNode) tuple.getKeyNode();
} else {
throw new YAMLException("Keys must be scalars but found: " + tuple.getKeyNode());
}
Node valueNode = tuple.getValueNode();
// keys can only be Strings
keyNode.setType(String.class);
String key = (String) constructObject(keyNode);
try {
Property property = getProperty(beanType, key);
valueNode.setType(property.getType());
TypeDescription memberDescription = typeDefinitions.get(beanType);
boolean typeDetected = false;
if (memberDescription != null) {
switch (valueNode.getNodeId()) {
case sequence:
SequenceNode snode = (SequenceNode) valueNode;
Class<? extends Object> memberType = memberDescription
.getListPropertyType(key);
if (memberType != null) {
snode.setListType(memberType);
typeDetected = true;
} else if (property.getType().isArray()) {
snode.setListType(property.getType().getComponentType());
typeDetected = true;
}
break;
case mapping:
MappingNode mnode = (MappingNode) valueNode;
Class<? extends Object> keyType = memberDescription.getMapKeyType(key);
if (keyType != null) {
mnode.setTypes(keyType, memberDescription.getMapValueType(key));
typeDetected = true;
}
break;
default: // scalar
}
}
if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) {
// only if there is no explicit TypeDescription
Class<?>[] arguments = property.getActualTypeArguments();
if (arguments != null && arguments.length > 0) {
// type safe (generic) collection may contain the
// proper class
if (valueNode.getNodeId() == NodeId.sequence) {
Class<?> t = arguments[0];
SequenceNode snode = (SequenceNode) valueNode;
snode.setListType(t);
} else if (valueNode.getTag().equals(Tag.SET)) {
Class<?> t = arguments[0];
MappingNode mnode = (MappingNode) valueNode;
mnode.setOnlyKeyType(t);
mnode.setUseClassConstructor(true);
} else if (property.getType().isAssignableFrom(Map.class)) {
Class<?> ketType = arguments[0];
Class<?> valueType = arguments[1];
MappingNode mnode = (MappingNode) valueNode;
mnode.setTypes(ketType, valueType);
mnode.setUseClassConstructor(true);
} else {
// the type for collection entries cannot be
// detected
}
}
}
Object value = constructObject(valueNode);
// Correct when the property expects float but double was
// constructed
if (property.getType() == Float.TYPE || property.getType() == Float.class) {
if (value instanceof Double) {
value = ((Double) value).floatValue();
}
}
// Correct when the property a String but the value is binary
if (property.getType() == String.class && Tag.BINARY.equals(valueNode.getTag()) && value instanceof byte[]) {
value = new String((byte[])value);
}
property.set(object, value);
} catch (Exception e) {
throw new ConstructorException("Cannot create property=" + key
+ " for JavaBean=" + object, node.getStartMark(), e.getMessage(),
valueNode.getStartMark(), e);
}
}
return object;
}
protected Property getProperty(Class<? extends Object> type, String name)
throws IntrospectionException {
return getPropertyUtils().getProperty(type, name);
}
}
/**
* Construct an instance when the runtime class is not known but a global
* tag with a class name is defined. It delegates the construction to the
* appropriate constructor based on the node kind (scalar, sequence,
* mapping)
*/
protected class ConstructYamlObject implements Construct {
private Construct getConstructor(Node node) {
Class<?> cl = getClassForNode(node);
node.setType(cl);
// call the constructor as if the runtime class is defined
Construct constructor = yamlClassConstructors.get(node.getNodeId());
return constructor;
}
public Object construct(Node node) {
Object result = null;
try {
result = getConstructor(node).construct(node);
} catch (ConstructorException e) {
throw e;
} catch (Exception e) {
throw new ConstructorException(null, null, "Can't construct a java object for "
+ node.getTag() + "; exception=" + e.getMessage(), node.getStartMark(), e);
}
return result;
}
public void construct2ndStep(Node node, Object object) {
try {
getConstructor(node).construct2ndStep(node, object);
} catch (Exception e) {
throw new ConstructorException(null, null,
"Can't construct a second step for a java object for " + node.getTag()
+ "; exception=" + e.getMessage(), node.getStartMark(), e);
}
}
}
/**
* Construct scalar instance when the runtime class is known. Recursive
* structures are not supported.
*/
protected class ConstructScalar extends AbstractConstruct {
public Object construct(Node nnode) {
ScalarNode node = (ScalarNode) nnode;
Class<?> type = node.getType();
Object result;
if (type.isPrimitive() || type == String.class || Number.class.isAssignableFrom(type)
|| type == Boolean.class || Date.class.isAssignableFrom(type)
|| type == Character.class || type == BigInteger.class
|| type == BigDecimal.class || Enum.class.isAssignableFrom(type)
|| Tag.BINARY.equals(node.getTag()) || Calendar.class.isAssignableFrom(type) || type == UUID.class) {
// standard classes created directly
result = constructStandardJavaInstance(type, node);
} else {
// there must be only 1 constructor with 1 argument
java.lang.reflect.Constructor<?>[] javaConstructors = type
.getDeclaredConstructors();
int oneArgCount = 0;
java.lang.reflect.Constructor<?> javaConstructor = null;
for (java.lang.reflect.Constructor<?> c : javaConstructors) {
if (c.getParameterTypes().length == 1) {
oneArgCount++;
javaConstructor = c;
}
}
Object argument;
if (javaConstructor == null) {
throw new YAMLException("No single argument constructor found for " + type);
} else if (oneArgCount == 1) {
argument = constructStandardJavaInstance(
javaConstructor.getParameterTypes()[0], node);
} else {
// TODO it should be possible to use implicit types instead
// of forcing String. Resolver must be available here to
// obtain the implicit tag. Then we can set the tag and call
// callConstructor(node) to create the argument instance.
// On the other hand it may be safer to require a custom
// constructor to avoid guessing the argument class
argument = constructScalar(node);
try {
javaConstructor = type.getDeclaredConstructor(String.class);
} catch (Exception e) {
throw new YAMLException("Can't construct a java object for scalar "
+ node.getTag() + "; No String constructor found. Exception="
+ e.getMessage(), e);
}
}
try {
javaConstructor.setAccessible(true);
result = javaConstructor.newInstance(argument);
} catch (Exception e) {
throw new ConstructorException(null, null,
"Can't construct a java object for scalar " + node.getTag()
+ "; exception=" + e.getMessage(), node.getStartMark(), e);
}
}
return result;
}
@SuppressWarnings("unchecked")
private Object constructStandardJavaInstance(@SuppressWarnings("rawtypes")
Class type, ScalarNode node) {
Object result;
if (type == String.class) {
Construct stringConstructor = yamlConstructors.get(Tag.STR);
result = stringConstructor.construct(node);
} else if (type == Boolean.class || type == Boolean.TYPE) {
Construct boolConstructor = yamlConstructors.get(Tag.BOOL);
result = boolConstructor.construct(node);
} else if (type == Character.class || type == Character.TYPE) {
Construct charConstructor = yamlConstructors.get(Tag.STR);
String ch = (String) charConstructor.construct(node);
if (ch.length() == 0) {
result = null;
} else if (ch.length() != 1) {
throw new YAMLException("Invalid node Character: '" + ch + "'; length: "
+ ch.length());
} else {
result = Character.valueOf(ch.charAt(0));
}
} else if (Date.class.isAssignableFrom(type)) {
Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP);
Date date = (Date) dateConstructor.construct(node);
if (type == Date.class) {
result = date;
} else {
try {
java.lang.reflect.Constructor<?> constr = type.getConstructor(long.class);
result = constr.newInstance(date.getTime());
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new YAMLException("Cannot construct: '" + type + "'");
}
}
} else if (type == Float.class || type == Double.class || type == Float.TYPE
|| type == Double.TYPE || type == BigDecimal.class) {
if (type == BigDecimal.class) {
result = new BigDecimal(node.getValue());
} else {
Construct doubleConstructor = yamlConstructors.get(Tag.FLOAT);
result = doubleConstructor.construct(node);
if (type == Float.class || type == Float.TYPE) {
result = new Float((Double) result);
}
}
} else if (type == Byte.class || type == Short.class || type == Integer.class
|| type == Long.class || type == BigInteger.class || type == Byte.TYPE
|| type == Short.TYPE || type == Integer.TYPE || type == Long.TYPE) {
Construct intConstructor = yamlConstructors.get(Tag.INT);
result = intConstructor.construct(node);
if (type == Byte.class || type == Byte.TYPE) {
result = Byte.valueOf(result.toString());
} else if (type == Short.class || type == Short.TYPE) {
result = Short.valueOf(result.toString());
} else if (type == Integer.class || type == Integer.TYPE) {
result = Integer.parseInt(result.toString());
} else if (type == Long.class || type == Long.TYPE) {
result = Long.valueOf(result.toString());
} else {
// only BigInteger left
result = new BigInteger(result.toString());
}
} else if (Enum.class.isAssignableFrom(type)) {
String enumValueName = node.getValue();
try {
result = Enum.valueOf(type, enumValueName);
} catch (Exception ex) {
throw new YAMLException("Unable to find enum value '" + enumValueName
+ "' for enum class: " + type.getName());
}
} else if (Calendar.class.isAssignableFrom(type)) {
ConstructYamlTimestamp contr = new ConstructYamlTimestamp();
contr.construct(node);
result = contr.getCalendar();
} else if (Number.class.isAssignableFrom(type)) {
ConstructYamlNumber contr = new ConstructYamlNumber();
result = contr.construct(node);
} else if (UUID.class == type) {
result = UUID.fromString(node.getValue());
} else {
if (yamlConstructors.containsKey(node.getTag())) {
result = yamlConstructors.get(node.getTag()).construct(node);
} else {
throw new YAMLException("Unsupported class: " + type);
}
}
return result;
}
}
/**
* Construct sequence (List, Array, or immutable object) when the runtime
* class is known.
*/
protected class ConstructSequence implements Construct {
@SuppressWarnings("unchecked")
public Object construct(Node node) {
SequenceNode snode = (SequenceNode) node;
if (Set.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
throw new YAMLException("Set cannot be recursive.");
} else {
return constructSet(snode);
}
} else if (Collection.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
return createDefaultList(snode.getValue().size());
} else {
return constructSequence(snode);
}
} else if (node.getType().isArray()) {
if (node.isTwoStepsConstruction()) {
return createArray(node.getType(), snode.getValue().size());
} else {
return constructArray(snode);
}
} else {
// create immutable object
List<java.lang.reflect.Constructor<?>> possibleConstructors = new ArrayList<java.lang.reflect.Constructor<?>>(
snode.getValue().size());
for (java.lang.reflect.Constructor<?> constructor : node
.getType().getDeclaredConstructors()) {
if (snode.getValue()
.size() == constructor.getParameterTypes().length) {
possibleConstructors.add(constructor);
}
}
if (!possibleConstructors.isEmpty()) {
if (possibleConstructors.size() == 1) {
Object[] argumentList = new Object[snode.getValue().size()];
java.lang.reflect.Constructor<?> c = possibleConstructors.get(0);
int index = 0;
for (Node argumentNode : snode.getValue()) {
Class<?> type = c.getParameterTypes()[index];
// set runtime classes for arguments
argumentNode.setType(type);
argumentList[index++] = constructObject(argumentNode);
}
try {
c.setAccessible(true);
return c.newInstance(argumentList);
} catch (Exception e) {
throw new YAMLException(e);
}
}
// use BaseConstructor
List<Object> argumentList = (List<Object>) constructSequence(snode);
Class<?>[] parameterTypes = new Class[argumentList.size()];
int index = 0;
for (Object parameter : argumentList) {
parameterTypes[index] = parameter.getClass();
index++;
}
for (java.lang.reflect.Constructor<?> c : possibleConstructors) {
Class<?>[] argTypes = c.getParameterTypes();
boolean foundConstructor = true;
for (int i = 0; i < argTypes.length; i++) {
if (!wrapIfPrimitive(argTypes[i]).isAssignableFrom(parameterTypes[i])) {
foundConstructor = false;
break;
}
}
if (foundConstructor) {
try {
c.setAccessible(true);
return c.newInstance(argumentList.toArray());
} catch (Exception e) {
throw new YAMLException(e);
}
}
}
}
throw new YAMLException("No suitable constructor with "
+ String.valueOf(snode.getValue().size()) + " arguments found for "
+ node.getType());
}
}
private final Class<? extends Object> wrapIfPrimitive(Class<?> clazz) {
if (!clazz.isPrimitive()) {
return clazz;
}
if (clazz == Integer.TYPE) {
return Integer.class;
}
if (clazz == Float.TYPE) {
return Float.class;
}
if (clazz == Double.TYPE) {
return Double.class;
}
if (clazz == Boolean.TYPE) {
return Boolean.class;
}
if (clazz == Long.TYPE) {
return Long.class;
}
if (clazz == Character.TYPE) {
return Character.class;
}
if (clazz == Short.TYPE) {
return Short.class;
}
if (clazz == Byte.TYPE) {
return Byte.class;
}
throw new YAMLException("Unexpected primitive " + clazz);
}
@SuppressWarnings("unchecked")
public void construct2ndStep(Node node, Object object) {
SequenceNode snode = (SequenceNode) node;
if (List.class.isAssignableFrom(node.getType())) {
List<Object> list = (List<Object>) object;
constructSequenceStep2(snode, list);
} else if (node.getType().isArray()) {
constructArrayStep2(snode, object);
} else {
throw new YAMLException("Immutable objects cannot be recursive.");
}
}
}
protected Class<?> getClassForNode(Node node) {
Class<? extends Object> classForTag = typeTags.get(node.getTag());
if (classForTag == null) {
String name = node.getTag().getClassName();
Class<?> cl;
try {
cl = getClassForName(name);
} catch (ClassNotFoundException e) {
throw new YAMLException("Class not found: " + name);
}
typeTags.put(node.getTag(), cl);
return cl;
} else {
return classForTag;
}
}
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
try {
return Class.forName(name, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
return Class.forName(name);
}
}
}

View File

@ -1,33 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.error.MarkedYAMLException;
public class ConstructorException extends MarkedYAMLException {
private static final long serialVersionUID = -8816339931365239910L;
protected ConstructorException(String context, Mark contextMark, String problem,
Mark problemMark, Throwable cause) {
super(context, contextMark, problem, problemMark, cause);
}
protected ConstructorException(String context, Mark contextMark, String problem,
Mark problemMark) {
this(context, contextMark, problem, problemMark, null);
}
}

View File

@ -1,40 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
/**
* Construct instances with a custom Class Loader.
*/
public class CustomClassLoaderConstructor extends Constructor {
private ClassLoader loader = CustomClassLoaderConstructor.class.getClassLoader();
public CustomClassLoaderConstructor(ClassLoader cLoader) {
this(Object.class, cLoader);
}
public CustomClassLoaderConstructor(Class<? extends Object> theRoot, ClassLoader theLoader) {
super(theRoot);
if (theLoader == null) {
throw new NullPointerException("Loader must be provided.");
}
this.loader = theLoader;
}
@Override
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
return Class.forName(name, true, loader);
}
}

View File

@ -1,553 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.constructor;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Construct standard Java classes
*/
public class SafeConstructor extends BaseConstructor {
public static final ConstructUndefined undefinedConstructor = new ConstructUndefined();
public SafeConstructor() {
this.yamlConstructors.put(Tag.NULL, new ConstructYamlNull());
this.yamlConstructors.put(Tag.BOOL, new ConstructYamlBool());
this.yamlConstructors.put(Tag.INT, new ConstructYamlInt());
this.yamlConstructors.put(Tag.FLOAT, new ConstructYamlFloat());
this.yamlConstructors.put(Tag.BINARY, new ConstructYamlBinary());
this.yamlConstructors.put(Tag.TIMESTAMP, new ConstructYamlTimestamp());
this.yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
this.yamlConstructors.put(Tag.PAIRS, new ConstructYamlPairs());
this.yamlConstructors.put(Tag.SET, new ConstructYamlSet());
this.yamlConstructors.put(Tag.STR, new ConstructYamlStr());
this.yamlConstructors.put(Tag.SEQ, new ConstructYamlSeq());
this.yamlConstructors.put(Tag.MAP, new ConstructYamlMap());
this.yamlConstructors.put(null, undefinedConstructor);
this.yamlClassConstructors.put(NodeId.scalar, undefinedConstructor);
this.yamlClassConstructors.put(NodeId.sequence, undefinedConstructor);
this.yamlClassConstructors.put(NodeId.mapping, undefinedConstructor);
}
protected void flattenMapping(MappingNode node) {
// perform merging only on nodes containing merge node(s)
processDuplicateKeys(node);
if (node.isMerged()) {
node.setValue(mergeNode(node, true, new HashMap<Object, Integer>(),
new ArrayList<NodeTuple>()));
}
}
protected void processDuplicateKeys(MappingNode node) {
List<NodeTuple> nodeValue = node.getValue();
Map<Object, Integer> keys = new HashMap<Object, Integer>(nodeValue.size());
Deque<Integer> toRemove = new ArrayDeque<Integer>();
int i = 0;
for (NodeTuple tuple : nodeValue) {
Node keyNode = tuple.getKeyNode();
if (!keyNode.getTag().equals(Tag.MERGE)) {
Object key = constructObject(keyNode);
if (key != null) {
try {
key.hashCode();// check circular dependencies
} catch (Exception e) {
throw new ConstructorException("while constructing a mapping",
node.getStartMark(), "found unacceptable key " + key,
tuple.getKeyNode().getStartMark(), e);
}
}
Integer prevIndex = keys.put(key, i);
if (prevIndex != null) {
if (!isAllowDuplicateKeys()) {
throw new IllegalStateException("duplicate key: " + key);
}
toRemove.add(prevIndex);
}
}
i = i + 1;
}
Iterator<Integer> indicies2remove = toRemove.descendingIterator();
while (indicies2remove.hasNext()) {
nodeValue.remove(indicies2remove.next().intValue());
}
}
/**
* Does merge for supplied mapping node.
*
* @param node
* where to merge
* @param isPreffered
* true if keys of node should take precedence over others...
* @param key2index
* maps already merged keys to index from values
* @param values
* collects merged NodeTuple
* @return list of the merged NodeTuple (to be set as value for the
* MappingNode)
*/
private List<NodeTuple> mergeNode(MappingNode node, boolean isPreffered,
Map<Object, Integer> key2index, List<NodeTuple> values) {
Iterator<NodeTuple> iter = node.getValue().iterator();
while (iter.hasNext()) {
final NodeTuple nodeTuple = iter.next();
final Node keyNode = nodeTuple.getKeyNode();
final Node valueNode = nodeTuple.getValueNode();
if (keyNode.getTag().equals(Tag.MERGE)) {
iter.remove();
switch (valueNode.getNodeId()) {
case mapping:
MappingNode mn = (MappingNode) valueNode;
mergeNode(mn, false, key2index, values);
break;
case sequence:
SequenceNode sn = (SequenceNode) valueNode;
List<Node> vals = sn.getValue();
for (Node subnode : vals) {
if (!(subnode instanceof MappingNode)) {
throw new ConstructorException("while constructing a mapping",
node.getStartMark(),
"expected a mapping for merging, but found "
+ subnode.getNodeId(),
subnode.getStartMark());
}
MappingNode mnode = (MappingNode) subnode;
mergeNode(mnode, false, key2index, values);
}
break;
default:
throw new ConstructorException("while constructing a mapping",
node.getStartMark(),
"expected a mapping or list of mappings for merging, but found "
+ valueNode.getNodeId(),
valueNode.getStartMark());
}
} else {
// we need to construct keys to avoid duplications
Object key = constructObject(keyNode);
if (!key2index.containsKey(key)) { // 1st time merging key
values.add(nodeTuple);
// keep track where tuple for the key is
key2index.put(key, values.size() - 1);
} else if (isPreffered) { // there is value for the key, but we
// need to override it
// change value for the key using saved position
values.set(key2index.get(key), nodeTuple);
}
}
}
return values;
}
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
flattenMapping(node);
super.constructMapping2ndStep(node, mapping);
}
@Override
protected void constructSet2ndStep(MappingNode node, Set<Object> set) {
flattenMapping(node);
super.constructSet2ndStep(node, set);
}
public class ConstructYamlNull extends AbstractConstruct {
public Object construct(Node node) {
constructScalar((ScalarNode) node);
return null;
}
}
private final static Map<String, Boolean> BOOL_VALUES = new HashMap<String, Boolean>();
static {
BOOL_VALUES.put("yes", Boolean.TRUE);
BOOL_VALUES.put("no", Boolean.FALSE);
BOOL_VALUES.put("true", Boolean.TRUE);
BOOL_VALUES.put("false", Boolean.FALSE);
BOOL_VALUES.put("on", Boolean.TRUE);
BOOL_VALUES.put("off", Boolean.FALSE);
}
public class ConstructYamlBool extends AbstractConstruct {
public Object construct(Node node) {
String val = (String) constructScalar((ScalarNode) node);
return BOOL_VALUES.get(val.toLowerCase());
}
}
public class ConstructYamlInt extends AbstractConstruct {
public Object construct(Node node) {
String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
int sign = +1;
char first = value.charAt(0);
if (first == '-') {
sign = -1;
value = value.substring(1);
} else if (first == '+') {
value = value.substring(1);
}
int base = 10;
if ("0".equals(value)) {
return Integer.valueOf(0);
} else if (value.startsWith("0b")) {
value = value.substring(2);
base = 2;
} else if (value.startsWith("0x")) {
value = value.substring(2);
base = 16;
} else if (value.startsWith("0")) {
value = value.substring(1);
base = 8;
} else if (value.indexOf(':') != -1) {
String[] digits = value.split(":");
int bes = 1;
int val = 0;
for (int i = 0, j = digits.length; i < j; i++) {
val += Long.parseLong(digits[j - i - 1]) * bes;
bes *= 60;
}
return createNumber(sign, String.valueOf(val), 10);
} else {
return createNumber(sign, value, 10);
}
return createNumber(sign, value, base);
}
}
private Number createNumber(int sign, String number, int radix) {
Number result;
if (sign < 0) {
number = "-" + number;
}
try {
result = Integer.valueOf(number, radix);
} catch (NumberFormatException e) {
try {
result = Long.valueOf(number, radix);
} catch (NumberFormatException e1) {
result = new BigInteger(number, radix);
}
}
return result;
}
public class ConstructYamlFloat extends AbstractConstruct {
public Object construct(Node node) {
String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
int sign = +1;
char first = value.charAt(0);
if (first == '-') {
sign = -1;
value = value.substring(1);
} else if (first == '+') {
value = value.substring(1);
}
String valLower = value.toLowerCase();
if (".inf".equals(valLower)) {
return new Double(sign == -1 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
} else if (".nan".equals(valLower)) {
return new Double(Double.NaN);
} else if (value.indexOf(':') != -1) {
String[] digits = value.split(":");
int bes = 1;
double val = 0.0;
for (int i = 0, j = digits.length; i < j; i++) {
val += Double.parseDouble(digits[j - i - 1]) * bes;
bes *= 60;
}
return new Double(sign * val);
} else {
Double d = Double.valueOf(value);
return new Double(d.doubleValue() * sign);
}
}
}
public class ConstructYamlBinary extends AbstractConstruct {
public Object construct(Node node) {
// Ignore white spaces for base64 encoded scalar
String noWhiteSpaces = constructScalar((ScalarNode) node).toString().replaceAll("\\s",
"");
byte[] decoded = Base64Coder.decode(noWhiteSpaces.toCharArray());
return decoded;
}
}
public class ConstructYamlNumber extends AbstractConstruct {
private final NumberFormat nf = NumberFormat.getInstance();
public Object construct(Node node) {
ScalarNode scalar = (ScalarNode) node;
try {
return nf.parse(scalar.getValue());
} catch (ParseException e) {
String lowerCaseValue = scalar.getValue().toLowerCase();
if (lowerCaseValue.contains("inf") || lowerCaseValue.contains("nan")) {
/*
* Non-finites such as (+/-)infinity and NaN are not
* parseable by NumberFormat when these `Double` values are
* dumped by snakeyaml. Delegate to the `Tag.FLOAT`
* constructor when for this expected failure cause.
*/
return yamlConstructors.get(Tag.FLOAT).construct(node);
} else {
throw new IllegalArgumentException(
"Unable to parse as Number: " + scalar.getValue());
}
}
}
}
private final static Pattern TIMESTAMP_REGEXP = Pattern.compile(
"^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$");
private final static Pattern YMD_REGEXP = Pattern
.compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");
public static class ConstructYamlTimestamp extends AbstractConstruct {
private Calendar calendar;
public Calendar getCalendar() {
return calendar;
}
public Object construct(Node node) {
ScalarNode scalar = (ScalarNode) node;
String nodeValue = scalar.getValue();
Matcher match = YMD_REGEXP.matcher(nodeValue);
if (match.matches()) {
String year_s = match.group(1);
String month_s = match.group(2);
String day_s = match.group(3);
calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.clear();
calendar.set(Calendar.YEAR, Integer.parseInt(year_s));
// Java's months are zero-based...
calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1); // x
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));
return calendar.getTime();
} else {
match = TIMESTAMP_REGEXP.matcher(nodeValue);
if (!match.matches()) {
throw new YAMLException("Unexpected timestamp: " + nodeValue);
}
String year_s = match.group(1);
String month_s = match.group(2);
String day_s = match.group(3);
String hour_s = match.group(4);
String min_s = match.group(5);
// seconds and milliseconds
String seconds = match.group(6);
String millis = match.group(7);
if (millis != null) {
seconds = seconds + "." + millis;
}
double fractions = Double.parseDouble(seconds);
int sec_s = (int) Math.round(Math.floor(fractions));
int usec = (int) Math.round((fractions - sec_s) * 1000);
// timezone
String timezoneh_s = match.group(8);
String timezonem_s = match.group(9);
TimeZone timeZone;
if (timezoneh_s != null) {
String time = timezonem_s != null ? ":" + timezonem_s : "00";
timeZone = TimeZone.getTimeZone("GMT" + timezoneh_s + time);
} else {
// no time zone provided
timeZone = TimeZone.getTimeZone("UTC");
}
calendar = Calendar.getInstance(timeZone);
calendar.set(Calendar.YEAR, Integer.parseInt(year_s));
// Java's months are zero-based...
calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1);
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour_s));
calendar.set(Calendar.MINUTE, Integer.parseInt(min_s));
calendar.set(Calendar.SECOND, sec_s);
calendar.set(Calendar.MILLISECOND, usec);
return calendar.getTime();
}
}
}
public class ConstructYamlOmap extends AbstractConstruct {
public Object construct(Node node) {
// Note: we do not check for duplicate keys, because it's too
// CPU-expensive.
Map<Object, Object> omap = new LinkedHashMap<Object, Object>();
if (!(node instanceof SequenceNode)) {
throw new ConstructorException("while constructing an ordered map",
node.getStartMark(), "expected a sequence, but found " + node.getNodeId(),
node.getStartMark());
}
SequenceNode snode = (SequenceNode) node;
for (Node subnode : snode.getValue()) {
if (!(subnode instanceof MappingNode)) {
throw new ConstructorException("while constructing an ordered map",
node.getStartMark(),
"expected a mapping of length 1, but found " + subnode.getNodeId(),
subnode.getStartMark());
}
MappingNode mnode = (MappingNode) subnode;
if (mnode.getValue().size() != 1) {
throw new ConstructorException("while constructing an ordered map",
node.getStartMark(), "expected a single mapping item, but found "
+ mnode.getValue().size() + " items",
mnode.getStartMark());
}
Node keyNode = mnode.getValue().get(0).getKeyNode();
Node valueNode = mnode.getValue().get(0).getValueNode();
Object key = constructObject(keyNode);
Object value = constructObject(valueNode);
omap.put(key, value);
}
return omap;
}
}
// Note: the same code as `construct_yaml_omap`.
public class ConstructYamlPairs extends AbstractConstruct {
public Object construct(Node node) {
// Note: we do not check for duplicate keys, because it's too
// CPU-expensive.
if (!(node instanceof SequenceNode)) {
throw new ConstructorException("while constructing pairs", node.getStartMark(),
"expected a sequence, but found " + node.getNodeId(), node.getStartMark());
}
SequenceNode snode = (SequenceNode) node;
List<Object[]> pairs = new ArrayList<Object[]>(snode.getValue().size());
for (Node subnode : snode.getValue()) {
if (!(subnode instanceof MappingNode)) {
throw new ConstructorException("while constructingpairs", node.getStartMark(),
"expected a mapping of length 1, but found " + subnode.getNodeId(),
subnode.getStartMark());
}
MappingNode mnode = (MappingNode) subnode;
if (mnode.getValue().size() != 1) {
throw new ConstructorException("while constructing pairs", node.getStartMark(),
"expected a single mapping item, but found " + mnode.getValue().size()
+ " items",
mnode.getStartMark());
}
Node keyNode = mnode.getValue().get(0).getKeyNode();
Node valueNode = mnode.getValue().get(0).getValueNode();
Object key = constructObject(keyNode);
Object value = constructObject(valueNode);
pairs.add(new Object[] { key, value });
}
return pairs;
}
}
public class ConstructYamlSet implements Construct {
public Object construct(Node node) {
if (node.isTwoStepsConstruction()) {
return createDefaultSet();
} else {
return constructSet((MappingNode) node);
}
}
@SuppressWarnings("unchecked")
public void construct2ndStep(Node node, Object object) {
if (node.isTwoStepsConstruction()) {
constructSet2ndStep((MappingNode) node, (Set<Object>) object);
} else {
throw new YAMLException("Unexpected recursive set structure. Node: " + node);
}
}
}
public class ConstructYamlStr extends AbstractConstruct {
public Object construct(Node node) {
return constructScalar((ScalarNode) node);
}
}
public class ConstructYamlSeq implements Construct {
public Object construct(Node node) {
SequenceNode seqNode = (SequenceNode) node;
if (node.isTwoStepsConstruction()) {
return createDefaultList(seqNode.getValue().size());
} else {
return constructSequence(seqNode);
}
}
@SuppressWarnings("unchecked")
public void construct2ndStep(Node node, Object data) {
if (node.isTwoStepsConstruction()) {
constructSequenceStep2((SequenceNode) node, (List<Object>) data);
} else {
throw new YAMLException("Unexpected recursive sequence structure. Node: " + node);
}
}
}
public class ConstructYamlMap implements Construct {
public Object construct(Node node) {
if (node.isTwoStepsConstruction()) {
return createDefaultMap();
} else {
return constructMapping((MappingNode) node);
}
}
@SuppressWarnings("unchecked")
public void construct2ndStep(Node node, Object object) {
if (node.isTwoStepsConstruction()) {
constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object);
} else {
throw new YAMLException("Unexpected recursive mapping structure. Node: " + node);
}
}
}
public static final class ConstructUndefined extends AbstractConstruct {
public Object construct(Node node) {
throw new ConstructorException(null, null,
"could not determine a constructor for the tag " + node.getTag(),
node.getStartMark());
}
}
}

View File

@ -1,24 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.emitter;
import java.io.IOException;
import org.yaml.snakeyaml.events.Event;
public interface Emitable {
void emit(Event event) throws IOException;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.emitter;
import org.yaml.snakeyaml.error.YAMLException;
public class EmitterException extends YAMLException {
private static final long serialVersionUID = -8280070025452995908L;
public EmitterException(String msg) {
super(msg);
}
}

View File

@ -1,25 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.emitter;
import java.io.IOException;
/**
* Python's methods are first class object. Java needs a class.
*/
interface EmitterState {
void expect() throws IOException;
}

View File

@ -1,37 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.emitter;
public final class ScalarAnalysis {
public String scalar;
public boolean empty;
public boolean multiline;
public boolean allowFlowPlain;
public boolean allowBlockPlain;
public boolean allowSingleQuoted;
public boolean allowBlock;
public ScalarAnalysis(String scalar, boolean empty, boolean multiline, boolean allowFlowPlain,
boolean allowBlockPlain, boolean allowSingleQuoted, boolean allowBlock) {
this.scalar = scalar;
this.empty = empty;
this.multiline = multiline;
this.allowFlowPlain = allowFlowPlain;
this.allowBlockPlain = allowBlockPlain;
this.allowSingleQuoted = allowSingleQuoted;
this.allowBlock = allowBlock;
}
}

View File

@ -1,137 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.error;
import java.io.Serializable;
import org.yaml.snakeyaml.scanner.Constant;
/**
* It's just a record and its only use is producing nice error messages. Parser
* does not use it for any other purposes.
*/
public final class Mark implements Serializable {
private String name;
private int index;
private int line;
private int column;
private String buffer;
private int pointer;
public Mark(String name, int index, int line, int column, String buffer, int pointer) {
super();
this.name = name;
this.index = index;
this.line = line;
this.column = column;
this.buffer = buffer;
this.pointer = pointer;
}
private boolean isLineBreak(int c) {
return Constant.NULL_OR_LINEBR.has(c);
}
public String get_snippet(int indent, int max_length) {
if (buffer == null) {
return null;
}
float half = max_length / 2 - 1;
int start = pointer;
String head = "";
while ((start > 0) && !isLineBreak(buffer.codePointAt(start - 1))) {
start -= 1;
if (pointer - start > half) {
head = " ... ";
start += 5;
break;
}
}
String tail = "";
int end = pointer;
while ((end < buffer.length()) && !isLineBreak(buffer.codePointAt(end))) {
end += 1;
if (end - pointer > half) {
tail = " ... ";
end -= 5;
break;
}
}
String snippet = buffer.substring(start, end);
StringBuilder result = new StringBuilder();
for (int i = 0; i < indent; i++) {
result.append(" ");
}
result.append(head);
result.append(snippet);
result.append(tail);
result.append("\n");
for (int i = 0; i < indent + pointer - start + head.length(); i++) {
result.append(" ");
}
result.append("^");
return result.toString();
}
public String get_snippet() {
return get_snippet(4, 75);
}
@Override
public String toString() {
String snippet = get_snippet();
StringBuilder where = new StringBuilder(" in ");
where.append(name);
where.append(", line ");
where.append(line + 1);
where.append(", column ");
where.append(column + 1);
if (snippet != null) {
where.append(":\n");
where.append(snippet);
}
return where.toString();
}
public String getName() {
return name;
}
/**
* starts with 0
* @return line number
*/
public int getLine() {
return line;
}
/**
* starts with 0
* @return column number
*/
public int getColumn() {
return column;
}
/**
* starts with 0
* @return character number
*/
public int getIndex() {
return index;
}
}

View File

@ -1,101 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.error;
public class MarkedYAMLException extends YAMLException {
private static final long serialVersionUID = -9119388488683035101L;
private String context;
private Mark contextMark;
private String problem;
private Mark problemMark;
private String note;
protected MarkedYAMLException(String context, Mark contextMark, String problem,
Mark problemMark, String note) {
this(context, contextMark, problem, problemMark, note, null);
}
protected MarkedYAMLException(String context, Mark contextMark, String problem,
Mark problemMark, String note, Throwable cause) {
super(context + "; " + problem + "; " + problemMark, cause);
this.context = context;
this.contextMark = contextMark;
this.problem = problem;
this.problemMark = problemMark;
this.note = note;
}
protected MarkedYAMLException(String context, Mark contextMark, String problem, Mark problemMark) {
this(context, contextMark, problem, problemMark, null, null);
}
protected MarkedYAMLException(String context, Mark contextMark, String problem,
Mark problemMark, Throwable cause) {
this(context, contextMark, problem, problemMark, null, cause);
}
@Override
public String getMessage() {
return toString();
}
@Override
public String toString() {
StringBuilder lines = new StringBuilder();
if (context != null) {
lines.append(context);
lines.append("\n");
}
if (contextMark != null
&& (problem == null || problemMark == null
|| contextMark.getName().equals(problemMark.getName())
|| (contextMark.getLine() != problemMark.getLine()) || (contextMark
.getColumn() != problemMark.getColumn()))) {
lines.append(contextMark.toString());
lines.append("\n");
}
if (problem != null) {
lines.append(problem);
lines.append("\n");
}
if (problemMark != null) {
lines.append(problemMark.toString());
lines.append("\n");
}
if (note != null) {
lines.append(note);
lines.append("\n");
}
return lines.toString();
}
public String getContext() {
return context;
}
public Mark getContextMark() {
return contextMark;
}
public String getProblem() {
return problem;
}
public Mark getProblemMark() {
return problemMark;
}
}

View File

@ -1,32 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.error;
public class YAMLException extends RuntimeException {
private static final long serialVersionUID = -4738336175050337570L;
public YAMLException(String message) {
super(message);
}
public YAMLException(Throwable cause) {
super(cause);
}
public YAMLException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,32 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the inclusion of a previously anchored node.
*/
public final class AliasEvent extends NodeEvent {
public AliasEvent(String anchor, Mark startMark, Mark endMark) {
super(anchor, startMark, endMark);
}
@Override
public boolean is(Event.ID id) {
return ID.Alias == id;
}
}

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Base class for the end events of the collection nodes.
*/
public abstract class CollectionEndEvent extends Event {
public CollectionEndEvent(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
}

View File

@ -1,73 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Base class for the start events of the collection nodes.
*/
public abstract class CollectionStartEvent extends NodeEvent {
private final String tag;
// The implicit flag of a collection start event indicates if the tag may be
// omitted when the collection is emitted
private final boolean implicit;
// flag indicates if a collection is block or flow
private final Boolean flowStyle;
public CollectionStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
Mark endMark, Boolean flowStyle) {
super(anchor, startMark, endMark);
this.tag = tag;
this.implicit = implicit;
this.flowStyle = flowStyle;
}
/**
* Tag of this collection.
*
* @return The tag of this collection, or <code>null</code> if no explicit
* tag is available.
*/
public String getTag() {
return this.tag;
}
/**
* <code>true</code> if the tag can be omitted while this collection is
* emitted.
*
* @return True if the tag can be omitted while this collection is emitted.
*/
public boolean getImplicit() {
return this.implicit;
}
/**
* <code>true</code> if this collection is in flow style, <code>false</code>
* for block style.
*
* @return If this collection is in flow style.
*/
public Boolean getFlowStyle() {
return this.flowStyle;
}
@Override
protected String getArguments() {
return super.getArguments() + ", tag=" + tag + ", implicit=" + implicit;
}
}

View File

@ -1,42 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the end of a document.
* <p>
* This event follows the document's content.
* </p>
*/
public final class DocumentEndEvent extends Event {
private final boolean explicit;
public DocumentEndEvent(Mark startMark, Mark endMark, boolean explicit) {
super(startMark, endMark);
this.explicit = explicit;
}
public boolean getExplicit() {
return explicit;
}
@Override
public boolean is(Event.ID id) {
return ID.DocumentEnd == id;
}
}

View File

@ -1,76 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions.Version;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the beginning of a document.
* <p>
* This event followed by the document's content and a {@link DocumentEndEvent}.
* </p>
*/
public final class DocumentStartEvent extends Event {
private final boolean explicit;
private final Version version;
private final Map<String, String> tags;
public DocumentStartEvent(Mark startMark, Mark endMark, boolean explicit, Version version,
Map<String, String> tags) {
super(startMark, endMark);
this.explicit = explicit;
this.version = version;
// TODO enforce not null
// if (tags == null) {
// throw new NullPointerException("Tags must be provided.");
// }
this.tags = tags;
}
public boolean getExplicit() {
return explicit;
}
/**
* YAML version the document conforms to.
*
* @return <code>null</code>if the document has no explicit
* <code>%YAML</code> directive. Otherwise an array with two
* components, the major and minor part of the version (in this
* order).
*/
public Version getVersion() {
return version;
}
/**
* Tag shorthands as defined by the <code>%TAG</code> directive.
*
* @return Mapping of 'handles' to 'prefixes' (the handles include the '!'
* characters).
*/
public Map<String, String> getTags() {
return tags;
}
@Override
public boolean is(Event.ID id) {
return ID.DocumentStart == id;
}
}

View File

@ -1,79 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Basic unit of output from a {@link org.yaml.snakeyaml.parser.Parser} or input
* of a {@link org.yaml.snakeyaml.emitter.Emitter}.
*/
public abstract class Event {
public enum ID {
Alias, DocumentEnd, DocumentStart, MappingEnd, MappingStart, Scalar, SequenceEnd, SequenceStart, StreamEnd, StreamStart
}
private final Mark startMark;
private final Mark endMark;
public Event(Mark startMark, Mark endMark) {
this.startMark = startMark;
this.endMark = endMark;
}
public String toString() {
return "<" + this.getClass().getName() + "(" + getArguments() + ")>";
}
public Mark getStartMark() {
return startMark;
}
public Mark getEndMark() {
return endMark;
}
/**
* Generate human readable representation of the Event
* @see "__repr__ for Event in PyYAML"
* @return representation fore humans
*/
protected String getArguments() {
return "";
}
public abstract boolean is(Event.ID id);
/*
* for tests only
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Event) {
return toString().equals(obj.toString());
} else {
return false;
}
}
/*
* for tests only
*/
@Override
public int hashCode() {
return toString().hashCode();
}
}

View File

@ -1,58 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
/**
* The implicit flag of a scalar event is a pair of boolean values that indicate
* if the tag may be omitted when the scalar is emitted in a plain and non-plain
* style correspondingly.
*
* @see <a href="http://pyyaml.org/wiki/PyYAMLDocumentation#Events">Events</a>
*/
public class ImplicitTuple {
private final boolean plain;
private final boolean nonPlain;
public ImplicitTuple(boolean plain, boolean nonplain) {
this.plain = plain;
this.nonPlain = nonplain;
}
/**
* @return true when tag may be omitted when the scalar is emitted in a
* plain style.
*/
public boolean canOmitTagInPlainScalar() {
return plain;
}
/**
* @return true when tag may be omitted when the scalar is emitted in a
* non-plain style.
*/
public boolean canOmitTagInNonPlainScalar() {
return nonPlain;
}
public boolean bothFalse() {
return !plain && !nonPlain;
}
@Override
public String toString() {
return "implicit=[" + plain + ", " + nonPlain + "]";
}
}

View File

@ -1,35 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the end of a mapping node.
*
* @see MappingStartEvent
*/
public final class MappingEndEvent extends CollectionEndEvent {
public MappingEndEvent(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public boolean is(Event.ID id) {
return ID.MappingEnd == id;
}
}

View File

@ -1,44 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the beginning of a mapping node.
* <p>
* This event is followed by a number of key value pairs. <br>
* The pairs are not in any particular order. However, the value always directly
* follows the corresponding key. <br>
* After the key value pairs follows a {@link MappingEndEvent}.
* </p>
* <p>
* There must be an even number of node events between the start and end event.
* </p>
*
* @see MappingEndEvent
*/
public final class MappingStartEvent extends CollectionStartEvent {
public MappingStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
Mark endMark, Boolean flowStyle) {
super(anchor, tag, implicit, startMark, endMark, flowStyle);
}
@Override
public boolean is(Event.ID id) {
return ID.MappingStart == id;
}
}

View File

@ -1,49 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Base class for all events that mark the beginning of a node.
*/
public abstract class NodeEvent extends Event {
private final String anchor;
public NodeEvent(String anchor, Mark startMark, Mark endMark) {
super(startMark, endMark);
this.anchor = anchor;
}
/**
* Node anchor by which this node might later be referenced by a
* {@link AliasEvent}.
* <p>
* Note that {@link AliasEvent}s are by it self <code>NodeEvent</code>s and
* use this property to indicate the referenced anchor.
*
* @return Anchor of this node or <code>null</code> if no anchor is defined.
*/
public String getAnchor() {
return this.anchor;
}
@Override
protected String getArguments() {
return "anchor=" + anchor;
}
}

View File

@ -1,101 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks a scalar value.
*/
public final class ScalarEvent extends NodeEvent {
private final String tag;
// style flag of a scalar event indicates the style of the scalar. Possible
// values are None, '', '\'', '"', '|', '>'
private final Character style;
private final String value;
// The implicit flag of a scalar event is a pair of boolean values that
// indicate if the tag may be omitted when the scalar is emitted in a plain
// and non-plain style correspondingly.
private final ImplicitTuple implicit;
public ScalarEvent(String anchor, String tag, ImplicitTuple implicit, String value,
Mark startMark, Mark endMark, Character style) {
super(anchor, startMark, endMark);
this.tag = tag;
this.implicit = implicit;
this.value = value;
this.style = style;
}
/**
* Tag of this scalar.
*
* @return The tag of this scalar, or <code>null</code> if no explicit tag
* is available.
*/
public String getTag() {
return this.tag;
}
/**
* Style of the scalar.
* <dl>
* <dt>null</dt>
* <dd>Flow Style - Plain</dd>
* <dt>'\''</dt>
* <dd>Flow Style - Single-Quoted</dd>
* <dt>'"'</dt>
* <dd>Flow Style - Double-Quoted</dd>
* <dt>'|'</dt>
* <dd>Block Style - Literal</dd>
* <dt>'&gt;'</dt>
* <dd>Block Style - Folded</dd>
* </dl>
*
* @see <a href="http://yaml.org/spec/1.1/#id864487">Kind/Style
* Combinations</a>
* @return Style of the scalar.
*/
public Character getStyle() {
return this.style;
}
/**
* String representation of the value.
* <p>
* Without quotes and escaping.
* </p>
*
* @return Value as Unicode string.
*/
public String getValue() {
return this.value;
}
public ImplicitTuple getImplicit() {
return this.implicit;
}
@Override
protected String getArguments() {
return super.getArguments() + ", tag=" + tag + ", " + implicit + ", value=" + value;
}
@Override
public boolean is(Event.ID id) {
return ID.Scalar == id;
}
}

View File

@ -1,35 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the end of a sequence.
*
* @see SequenceStartEvent
*/
public final class SequenceEndEvent extends CollectionEndEvent {
public SequenceEndEvent(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public boolean is(Event.ID id) {
return ID.SequenceEnd == id;
}
}

View File

@ -1,39 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the beginning of a sequence node.
* <p>
* This event is followed by the elements contained in the sequence, and a
* {@link SequenceEndEvent}.
* </p>
*
* @see SequenceEndEvent
*/
public final class SequenceStartEvent extends CollectionStartEvent {
public SequenceStartEvent(String anchor, String tag, boolean implicit, Mark startMark,
Mark endMark, Boolean flowStyle) {
super(anchor, tag, implicit, startMark, endMark, flowStyle);
}
@Override
public boolean is(Event.ID id) {
return ID.SequenceStart == id;
}
}

View File

@ -1,40 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the end of a stream that might have contained multiple documents.
* <p>
* This event is the last event that a parser emits. Together with
* {@link StreamStartEvent} (which is the first event a parser emits) they mark
* the beginning and the end of a stream of documents.
* </p>
* <p>
* See {@link Event} for an exemplary output.
* </p>
*/
public final class StreamEndEvent extends Event {
public StreamEndEvent(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public boolean is(Event.ID id) {
return ID.StreamEnd == id;
}
}

View File

@ -1,41 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.events;
import org.yaml.snakeyaml.error.Mark;
/**
* Marks the start of a stream that might contain multiple documents.
* <p>
* This event is the first event that a parser emits. Together with
* {@link StreamEndEvent} (which is the last event a parser emits) they mark the
* beginning and the end of a stream of documents.
* </p>
* <p>
* See {@link Event} for an exemplary output.
* </p>
*/
public final class StreamStartEvent extends Event {
public StreamStartEvent(Mark startMark, Mark endMark) {
super(startMark, endMark);
}
@Override
public boolean is(Event.ID id) {
return ID.StreamStart == id;
}
}

View File

@ -1,237 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.extensions.compactnotation;
import java.beans.IntrospectionException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.constructor.Construct;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
/**
* Construct a custom Java instance out of a compact object notation format.
*/
public class CompactConstructor extends Constructor {
private static final Pattern GUESS_COMPACT = Pattern
.compile("\\p{Alpha}.*\\s*\\((?:,?\\s*(?:(?:\\w*)|(?:\\p{Alpha}\\w*\\s*=.+))\\s*)+\\)");
private static final Pattern FIRST_PATTERN = Pattern.compile("(\\p{Alpha}.*)(\\s*)\\((.*?)\\)");
private static final Pattern PROPERTY_NAME_PATTERN = Pattern
.compile("\\s*(\\p{Alpha}\\w*)\\s*=(.+)");
private Construct compactConstruct;
protected Object constructCompactFormat(ScalarNode node, CompactData data) {
try {
Object obj = createInstance(node, data);
Map<String, Object> properties = new HashMap<String, Object>(data.getProperties());
setProperties(obj, properties);
return obj;
} catch (Exception e) {
throw new YAMLException(e);
}
}
protected Object createInstance(ScalarNode node, CompactData data) throws Exception {
Class<?> clazz = getClassForName(data.getPrefix());
Class<?>[] args = new Class[data.getArguments().size()];
for (int i = 0; i < args.length; i++) {
// assume all the arguments are Strings
args[i] = String.class;
}
java.lang.reflect.Constructor<?> c = clazz.getDeclaredConstructor(args);
c.setAccessible(true);
return c.newInstance(data.getArguments().toArray());
}
protected void setProperties(Object bean, Map<String, Object> data) throws Exception {
if (data == null) {
throw new NullPointerException("Data for Compact Object Notation cannot be null.");
}
for (Map.Entry<String, Object> entry : data.entrySet()) {
String key = entry.getKey();
Property property = getPropertyUtils().getProperty(bean.getClass(), key);
try {
property.set(bean, entry.getValue());
} catch (IllegalArgumentException e) {
throw new YAMLException("Cannot set property='" + key + "' with value='"
+ data.get(key) + "' (" + data.get(key).getClass() + ") in " + bean);
}
}
}
public CompactData getCompactData(String scalar) {
if (!scalar.endsWith(")")) {
return null;
}
if (scalar.indexOf('(') < 0) {
return null;
}
Matcher m = FIRST_PATTERN.matcher(scalar);
if (m.matches()) {
String tag = m.group(1).trim();
String content = m.group(3);
CompactData data = new CompactData(tag);
if (content.length() == 0)
return data;
String[] names = content.split("\\s*,\\s*");
for (int i = 0; i < names.length; i++) {
String section = names[i];
if (section.indexOf('=') < 0) {
data.getArguments().add(section);
} else {
Matcher sm = PROPERTY_NAME_PATTERN.matcher(section);
if (sm.matches()) {
String name = sm.group(1);
String value = sm.group(2).trim();
data.getProperties().put(name, value);
} else {
return null;
}
}
}
return data;
}
return null;
}
private Construct getCompactConstruct() {
if (compactConstruct == null) {
compactConstruct = createCompactConstruct();
}
return compactConstruct;
}
protected Construct createCompactConstruct() {
return new ConstructCompactObject();
}
@Override
protected Construct getConstructor(Node node) {
if (node instanceof MappingNode) {
MappingNode mnode = (MappingNode) node;
List<NodeTuple> list = mnode.getValue();
if (list.size() == 1) {
NodeTuple tuple = list.get(0);
Node key = tuple.getKeyNode();
if (key instanceof ScalarNode) {
ScalarNode scalar = (ScalarNode) key;
if (GUESS_COMPACT.matcher(scalar.getValue()).matches()) {
return getCompactConstruct();
}
}
}
} else if (node instanceof ScalarNode) {
ScalarNode scalar = (ScalarNode) node;
if (GUESS_COMPACT.matcher(scalar.getValue()).matches()) {
return getCompactConstruct();
}
}
return super.getConstructor(node);
}
public class ConstructCompactObject extends ConstructMapping {
@Override
public void construct2ndStep(Node node, Object object) {
// Compact Object Notation may contain only one entry
MappingNode mnode = (MappingNode) node;
NodeTuple nodeTuple = mnode.getValue().iterator().next();
Node valueNode = nodeTuple.getValueNode();
if (valueNode instanceof MappingNode) {
valueNode.setType(object.getClass());
constructJavaBean2ndStep((MappingNode) valueNode, object);
} else {
// value is a list
applySequence(object, constructSequence((SequenceNode) valueNode));
}
}
/*
* MappingNode and ScalarNode end up here only they assumed to be a
* compact object's representation (@see getConstructor(Node) above)
*/
public Object construct(Node node) {
ScalarNode tmpNode = null;
if (node instanceof MappingNode) {
// Compact Object Notation may contain only one entry
MappingNode mnode = (MappingNode) node;
NodeTuple nodeTuple = mnode.getValue().iterator().next();
node.setTwoStepsConstruction(true);
tmpNode = (ScalarNode) nodeTuple.getKeyNode();
// return constructScalar((ScalarNode) keyNode);
} else {
tmpNode = (ScalarNode) node;
}
CompactData data = getCompactData(tmpNode.getValue());
if (data == null) { // TODO: Should we throw an exception here ?
return constructScalar(tmpNode);
}
return constructCompactFormat(tmpNode, data);
}
}
protected void applySequence(Object bean, List<?> value) {
try {
Property property = getPropertyUtils().getProperty(bean.getClass(),
getSequencePropertyName(bean.getClass()));
property.set(bean, value);
} catch (Exception e) {
throw new YAMLException(e);
}
}
/**
* Provide the name of the property which is used when the entries form a
* sequence. The property must be a List.
* @param bean the class to provide exactly one List property
* @return name of the List property
* @throws IntrospectionException if the bean cannot be introspected
*/
protected String getSequencePropertyName(Class<?> bean) throws IntrospectionException {
Set<Property> properties = getPropertyUtils().getProperties(bean);
for (Iterator<Property> iterator = properties.iterator(); iterator.hasNext();) {
Property property = iterator.next();
if (!List.class.isAssignableFrom(property.getType())) {
iterator.remove();
}
}
if (properties.size() == 0) {
throw new YAMLException("No list property found in " + bean);
} else if (properties.size() > 1) {
throw new YAMLException(
"Many list properties found in "
+ bean
+ "; Please override getSequencePropertyName() to specify which property to use.");
}
return properties.iterator().next().getName();
}
}

View File

@ -1,48 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.extensions.compactnotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CompactData {
private String prefix;
private List<String> arguments = new ArrayList<String>();
private Map<String, String> properties = new HashMap<String, String>();
public CompactData(String prefix) {
this.prefix = prefix;
}
public String getPrefix() {
return prefix;
}
public Map<String, String> getProperties() {
return properties;
}
public List<String> getArguments() {
return arguments;
}
@Override
public String toString() {
return "CompactData: " + prefix + " " + properties;
}
}

View File

@ -1,37 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.extensions.compactnotation;
public class PackageCompactConstructor extends CompactConstructor {
private String packageName;
public PackageCompactConstructor(String packageName) {
this.packageName = packageName;
}
@Override
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
if (name.indexOf('.') < 0) {
try {
Class<?> clazz = Class.forName(packageName + "." + name);
return clazz;
} catch (ClassNotFoundException e) {
// use super implementation
}
}
return super.getClassForName(name);
}
}

View File

@ -1,305 +0,0 @@
// Copyright 2003-2010 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
// www.source-code.biz, www.inventec.ch/chdh
//
// This module is multi-licensed and may be used under the terms
// of any of the following licenses:
//
// EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal
// LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html
// GPL, GNU General Public License, V2 or later, http://www.gnu.org/licenses/gpl.html
// AL, Apache License, V2.0 or later, http://www.apache.org/licenses
// BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php
//
// Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind.
package org.yaml.snakeyaml.external.biz.base64Coder;
/**
* A Base64 encoder/decoder.
*
* <p>
* This class is used to encode and decode data in Base64 format as described in
* RFC 1521.
*
* <p>
* Project home page: <a
* href="http://www.source-code.biz/base64coder/java/">www.
* source-code.biz/base64coder/java</a><br>
* Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
* Multi-licensed: EPL / LGPL / GPL / AL / BSD.
*/
public class Base64Coder {
// The line separator string of the operating system.
private static final String systemLineSeparator = System.getProperty("line.separator");
// Mapping table from 6-bit nibbles to Base64 characters.
private static char[] map1 = new char[64];
static {
int i = 0;
for (char c = 'A'; c <= 'Z'; c++)
map1[i++] = c;
for (char c = 'a'; c <= 'z'; c++)
map1[i++] = c;
for (char c = '0'; c <= '9'; c++)
map1[i++] = c;
map1[i++] = '+';
map1[i++] = '/';
}
// Mapping table from Base64 characters to 6-bit nibbles.
private static byte[] map2 = new byte[128];
static {
for (int i = 0; i < map2.length; i++)
map2[i] = -1;
for (int i = 0; i < 64; i++)
map2[map1[i]] = (byte) i;
}
/**
* Encodes a string into Base64 format. No blanks or line breaks are
* inserted.
*
* @param s
* A String to be encoded.
* @return A String containing the Base64 encoded data.
*/
public static String encodeString(String s) {
return new String(encode(s.getBytes()));
}
/**
* Encodes a byte array into Base 64 format and breaks the output into lines
* of 76 characters. This method is compatible with
* <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>.
*
* @param in
* An array containing the data bytes to be encoded.
* @return A String containing the Base64 encoded data, broken into lines.
*/
public static String encodeLines(byte[] in) {
return encodeLines(in, 0, in.length, 76, systemLineSeparator);
}
/**
* Encodes a byte array into Base 64 format and breaks the output into
* lines.
*
* @param in
* An array containing the data bytes to be encoded.
* @param iOff
* Offset of the first byte in <code>in</code> to be processed.
* @param iLen
* Number of bytes to be processed in <code>in</code>, starting
* at <code>iOff</code>.
* @param lineLen
* Line length for the output data. Should be a multiple of 4.
* @param lineSeparator
* The line separator to be used to separate the output lines.
* @return A String containing the Base64 encoded data, broken into lines.
*/
public static String encodeLines(byte[] in, int iOff, int iLen, int lineLen,
String lineSeparator) {
int blockLen = (lineLen * 3) / 4;
if (blockLen <= 0)
throw new IllegalArgumentException();
int lines = (iLen + blockLen - 1) / blockLen;
int bufLen = ((iLen + 2) / 3) * 4 + lines * lineSeparator.length();
StringBuilder buf = new StringBuilder(bufLen);
int ip = 0;
while (ip < iLen) {
int l = Math.min(iLen - ip, blockLen);
buf.append(encode(in, iOff + ip, l));
buf.append(lineSeparator);
ip += l;
}
return buf.toString();
}
/**
* Encodes a byte array into Base64 format. No blanks or line breaks are
* inserted in the output.
*
* @param in
* An array containing the data bytes to be encoded.
* @return A character array containing the Base64 encoded data.
*/
public static char[] encode(byte[] in) {
return encode(in, 0, in.length);
}
/**
* Encodes a byte array into Base64 format. No blanks or line breaks are
* inserted in the output.
*
* @param in
* An array containing the data bytes to be encoded.
* @param iLen
* Number of bytes to process in <code>in</code>.
* @return A character array containing the Base64 encoded data.
*/
public static char[] encode(byte[] in, int iLen) {
return encode(in, 0, iLen);
}
/**
* Encodes a byte array into Base64 format. No blanks or line breaks are
* inserted in the output.
*
* @param in
* An array containing the data bytes to be encoded.
* @param iOff
* Offset of the first byte in <code>in</code> to be processed.
* @param iLen
* Number of bytes to process in <code>in</code>, starting at
* <code>iOff</code>.
* @return A character array containing the Base64 encoded data.
*/
public static char[] encode(byte[] in, int iOff, int iLen) {
int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
int oLen = ((iLen + 2) / 3) * 4; // output length including padding
char[] out = new char[oLen];
int ip = iOff;
int iEnd = iOff + iLen;
int op = 0;
while (ip < iEnd) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iEnd ? in[ip++] & 0xff : 0;
int i2 = ip < iEnd ? in[ip++] & 0xff : 0;
int o0 = i0 >>> 2;
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
int o3 = i2 & 0x3F;
out[op++] = map1[o0];
out[op++] = map1[o1];
out[op] = op < oDataLen ? map1[o2] : '=';
op++;
out[op] = op < oDataLen ? map1[o3] : '=';
op++;
}
return out;
}
/**
* Decodes a string from Base64 format. No blanks or line breaks are allowed
* within the Base64 encoded input data.
*
* @param s
* A Base64 String to be decoded.
* @return A String containing the decoded data.
* @throws IllegalArgumentException
* If the input is not valid Base64 encoded data.
*/
public static String decodeString(String s) {
return new String(decode(s));
}
/**
* Decodes a byte array from Base64 format and ignores line separators, tabs
* and blanks. CR, LF, Tab and Space characters are ignored in the input
* data. This method is compatible with
* <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>.
*
* @param s
* A Base64 String to be decoded.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException
* If the input is not valid Base64 encoded data.
*/
public static byte[] decodeLines(String s) {
char[] buf = new char[s.length()];
int p = 0;
for (int ip = 0; ip < s.length(); ip++) {
char c = s.charAt(ip);
if (c != ' ' && c != '\r' && c != '\n' && c != '\t')
buf[p++] = c;
}
return decode(buf, 0, p);
}
/**
* Decodes a byte array from Base64 format. No blanks or line breaks are
* allowed within the Base64 encoded input data.
*
* @param s
* A Base64 String to be decoded.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException
* If the input is not valid Base64 encoded data.
*/
public static byte[] decode(String s) {
return decode(s.toCharArray());
}
/**
* Decodes a byte array from Base64 format. No blanks or line breaks are
* allowed within the Base64 encoded input data.
*
* @param in
* A character array containing the Base64 encoded data.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException
* If the input is not valid Base64 encoded data.
*/
public static byte[] decode(char[] in) {
return decode(in, 0, in.length);
}
/**
* Decodes a byte array from Base64 format. No blanks or line breaks are
* allowed within the Base64 encoded input data.
*
* @param in
* A character array containing the Base64 encoded data.
* @param iOff
* Offset of the first character in <code>in</code> to be
* processed.
* @param iLen
* Number of characters to process in <code>in</code>, starting
* at <code>iOff</code>.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException
* If the input is not valid Base64 encoded data.
*/
public static byte[] decode(char[] in, int iOff, int iLen) {
if (iLen % 4 != 0)
throw new IllegalArgumentException(
"Length of Base64 encoded input string is not a multiple of 4.");
while (iLen > 0 && in[iOff + iLen - 1] == '=')
iLen--;
int oLen = (iLen * 3) / 4;
byte[] out = new byte[oLen];
int ip = iOff;
int iEnd = iOff + iLen;
int op = 0;
while (ip < iEnd) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iEnd ? in[ip++] : 'A';
int i3 = ip < iEnd ? in[ip++] : 'A';
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
int b0 = map2[i0];
int b1 = map2[i1];
int b2 = map2[i2];
int b3 = map2[i3];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
int o0 = (b0 << 2) | (b1 >>> 4);
int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
int o2 = ((b2 & 3) << 6) | b3;
out[op++] = (byte) o0;
if (op < oLen)
out[op++] = (byte) o1;
if (op < oLen)
out[op++] = (byte) o2;
}
return out;
}
// Dummy constructor.
private Base64Coder() {
}
} // end class Base64Coder

View File

@ -1,97 +0,0 @@
/* Copyright (c) 2008 Google Inc.
*
* 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.yaml.snakeyaml.external.com.google.gdata.util.common.base;
/**
* An object that converts literal text into a format safe for inclusion in a
* particular context (such as an XML document). Typically (but not always), the
* inverse process of "unescaping" the text is performed automatically by the
* relevant parser.
*
* <p>
* For example, an XML escaper would convert the literal string
* {@code "Foo<Bar>"} into {@code "Foo&lt;Bar&gt;"} to prevent {@code "<Bar>"}
* from being confused with an XML tag. When the resulting XML document is
* parsed, the parser API will return this text as the original literal string
* {@code "Foo<Bar>"}.
*
* <p>
* An {@code Escaper} instance is required to be stateless, and safe when used
* concurrently by multiple threads.
*
* <p>
* Several popular escapers are defined as constants in the class
* {@link CharEscapers}. To create your own escapers, use
* {@link CharEscaperBuilder}, or extend {@link CharEscaper} or
* {@code UnicodeEscaper}.
*
*
*/
public interface Escaper {
/**
* Returns the escaped form of a given literal string.
*
* <p>
* Note that this method may treat input characters differently depending on
* the specific escaper implementation.
* <ul>
* <li>{@link UnicodeEscaper} handles <a
* href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a> correctly,
* including surrogate character pairs. If the input is badly formed the
* escaper should throw {@link IllegalArgumentException}.
* <li>{@link CharEscaper} handles Java characters independently and does
* not verify the input for well formed characters. A CharEscaper should not
* be used in situations where input is not guaranteed to be restricted to
* the Basic Multilingual Plane (BMP).
* </ul>
*
* @param string
* the literal string to be escaped
* @return the escaped form of {@code string}
* @throws NullPointerException
* if {@code string} is null
* @throws IllegalArgumentException
* if {@code string} contains badly formed UTF-16 or cannot be
* escaped for any other reason
*/
public String escape(String string);
/**
* Returns an {@code Appendable} instance which automatically escapes all
* text appended to it before passing the resulting text to an underlying
* {@code Appendable}.
*
* <p>
* Note that this method may treat input characters differently depending on
* the specific escaper implementation.
* <ul>
* <li>{@link UnicodeEscaper} handles <a
* href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a> correctly,
* including surrogate character pairs. If the input is badly formed the
* escaper should throw {@link IllegalArgumentException}.
* <li>{@link CharEscaper} handles Java characters independently and does
* not verify the input for well formed characters. A CharEscaper should not
* be used in situations where input is not guaranteed to be restricted to
* the Basic Multilingual Plane (BMP).
* </ul>
*
* @param out
* the underlying {@code Appendable} to append escaped output to
* @return an {@code Appendable} which passes text to {@code out} after
* escaping it.
*/
public Appendable escape(Appendable out);
}

View File

@ -1,281 +0,0 @@
/* Copyright (c) 2008 Google Inc.
*
* 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.yaml.snakeyaml.external.com.google.gdata.util.common.base;
/**
* A {@code UnicodeEscaper} that escapes some set of Java characters using the
* URI percent encoding scheme. The set of safe characters (those which remain
* unescaped) can be specified on construction.
*
* <p>
* For details on escaping URIs for use in web pages, see section 2.4 of <a
* href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
*
* <p>
* In most cases this class should not need to be used directly. If you have no
* special requirements for escaping your URIs, you should use either
* {@link CharEscapers#uriEscaper()} or {@link CharEscapers#uriEscaper(boolean)}.
*
* <p>
* When encoding a String, the following rules apply:
* <ul>
* <li>The alphanumeric characters "a" through "z", "A" through "Z" and "0"
* through "9" remain the same.
* <li>Any additionally specified safe characters remain the same.
* <li>If {@code plusForSpace} was specified, the space character " " is
* converted into a plus sign "+".
* <li>All other characters are converted into one or more bytes using UTF-8
* encoding and each byte is then represented by the 3-character string "%XY",
* where "XY" is the two-digit, uppercase, hexadecimal representation of the
* byte value.
* </ul>
*
* <p>
* RFC 2396 specifies the set of unreserved characters as "-", "_", ".", "!",
* "~", "*", "'", "(" and ")". It goes on to state:
*
* <p>
* <i>Unreserved characters can be escaped without changing the semantics of the
* URI, but this should not be done unless the URI is being used in a context
* that does not allow the unescaped character to appear.</i>
*
* <p>
* For performance reasons the only currently supported character encoding of
* this class is UTF-8.
*
* <p>
* <b>Note</b>: This escaper produces uppercase hexidecimal sequences. From <a
* href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>:<br>
* <i>"URI producers and normalizers should use uppercase hexadecimal digits for
* all percent-encodings."</i>
*
*
*/
public class PercentEscaper extends UnicodeEscaper {
/**
* A string of safe characters that mimics the behavior of
* {@link java.net.URLEncoder}.
*
*/
public static final String SAFECHARS_URLENCODER = "-_.*";
/**
* A string of characters that do not need to be encoded when used in URI
* path segments, as specified in RFC 3986. Note that some of these
* characters do need to be escaped when used in other parts of the URI.
*/
public static final String SAFEPATHCHARS_URLENCODER = "-_.!~*'()@:$&,;=";
/**
* A string of characters that do not need to be encoded when used in URI
* query strings, as specified in RFC 3986. Note that some of these
* characters do need to be escaped when used in other parts of the URI.
*/
public static final String SAFEQUERYSTRINGCHARS_URLENCODER = "-_.!~*'()@:$,;/?:";
// In some uri escapers spaces are escaped to '+'
private static final char[] URI_ESCAPED_SPACE = { '+' };
private static final char[] UPPER_HEX_DIGITS = "0123456789ABCDEF".toCharArray();
/**
* If true we should convert space to the {@code +} character.
*/
private final boolean plusForSpace;
/**
* An array of flags where for any {@code char c} if {@code safeOctets[c]}
* is true then {@code c} should remain unmodified in the output. If
* {@code c > safeOctets.length} then it should be escaped.
*/
private final boolean[] safeOctets;
/**
* Constructs a URI escaper with the specified safe characters and optional
* handling of the space character.
*
* @param safeChars
* a non null string specifying additional safe characters for
* this escaper (the ranges 0..9, a..z and A..Z are always safe
* and should not be specified here)
* @param plusForSpace
* true if ASCII space should be escaped to {@code +} rather than
* {@code %20}
* @throws IllegalArgumentException
* if any of the parameters were invalid
*/
public PercentEscaper(String safeChars, boolean plusForSpace) {
// Avoid any misunderstandings about the behavior of this escaper
if (safeChars.matches(".*[0-9A-Za-z].*")) {
throw new IllegalArgumentException(
"Alphanumeric characters are always 'safe' and should not be "
+ "explicitly specified");
}
// Avoid ambiguous parameters. Safe characters are never modified so if
// space is a safe character then setting plusForSpace is meaningless.
if (plusForSpace && safeChars.contains(" ")) {
throw new IllegalArgumentException(
"plusForSpace cannot be specified when space is a 'safe' character");
}
if (safeChars.contains("%")) {
throw new IllegalArgumentException("The '%' character cannot be specified as 'safe'");
}
this.plusForSpace = plusForSpace;
this.safeOctets = createSafeOctets(safeChars);
}
/**
* Creates a boolean[] with entries corresponding to the character values
* for 0-9, A-Z, a-z and those specified in safeChars set to true. The array
* is as small as is required to hold the given character information.
*/
private static boolean[] createSafeOctets(String safeChars) {
int maxChar = 'z';
char[] safeCharArray = safeChars.toCharArray();
for (char c : safeCharArray) {
maxChar = Math.max(c, maxChar);
}
boolean[] octets = new boolean[maxChar + 1];
for (int c = '0'; c <= '9'; c++) {
octets[c] = true;
}
for (int c = 'A'; c <= 'Z'; c++) {
octets[c] = true;
}
for (int c = 'a'; c <= 'z'; c++) {
octets[c] = true;
}
for (char c : safeCharArray) {
octets[c] = true;
}
return octets;
}
/*
* Overridden for performance. For unescaped strings this improved the
* performance of the uri escaper from ~760ns to ~400ns as measured by
* {@link CharEscapersBenchmark}.
*/
@Override
protected int nextEscapeIndex(CharSequence csq, int index, int end) {
for (; index < end; index++) {
char c = csq.charAt(index);
if (c >= safeOctets.length || !safeOctets[c]) {
break;
}
}
return index;
}
/*
* Overridden for performance. For unescaped strings this improved the
* performance of the uri escaper from ~400ns to ~170ns as measured by
* {@link CharEscapersBenchmark}.
*/
@Override
public String escape(String s) {
int slen = s.length();
for (int index = 0; index < slen; index++) {
char c = s.charAt(index);
if (c >= safeOctets.length || !safeOctets[c]) {
return escapeSlow(s, index);
}
}
return s;
}
/**
* Escapes the given Unicode code point in UTF-8.
*/
@Override
protected char[] escape(int cp) {
// We should never get negative values here but if we do it will throw
// an
// IndexOutOfBoundsException, so at least it will get spotted.
if (cp < safeOctets.length && safeOctets[cp]) {
return null;
} else if (cp == ' ' && plusForSpace) {
return URI_ESCAPED_SPACE;
} else if (cp <= 0x7F) {
// Single byte UTF-8 characters
// Start with "%--" and fill in the blanks
char[] dest = new char[3];
dest[0] = '%';
dest[2] = UPPER_HEX_DIGITS[cp & 0xF];
dest[1] = UPPER_HEX_DIGITS[cp >>> 4];
return dest;
} else if (cp <= 0x7ff) {
// Two byte UTF-8 characters [cp >= 0x80 && cp <= 0x7ff]
// Start with "%--%--" and fill in the blanks
char[] dest = new char[6];
dest[0] = '%';
dest[3] = '%';
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
cp >>>= 2;
dest[2] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[1] = UPPER_HEX_DIGITS[0xC | cp];
return dest;
} else if (cp <= 0xffff) {
// Three byte UTF-8 characters [cp >= 0x800 && cp <= 0xffff]
// Start with "%E-%--%--" and fill in the blanks
char[] dest = new char[9];
dest[0] = '%';
dest[1] = 'E';
dest[3] = '%';
dest[6] = '%';
dest[8] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[7] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
cp >>>= 2;
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
cp >>>= 2;
dest[2] = UPPER_HEX_DIGITS[cp];
return dest;
} else if (cp <= 0x10ffff) {
char[] dest = new char[12];
// Four byte UTF-8 characters [cp >= 0xffff && cp <= 0x10ffff]
// Start with "%F-%--%--%--" and fill in the blanks
dest[0] = '%';
dest[1] = 'F';
dest[3] = '%';
dest[6] = '%';
dest[9] = '%';
dest[11] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[10] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
cp >>>= 2;
dest[8] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[7] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
cp >>>= 2;
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
cp >>>= 4;
dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)];
cp >>>= 2;
dest[2] = UPPER_HEX_DIGITS[cp & 0x7];
return dest;
} else {
// If this ever happens it is due to bug in UnicodeEscaper, not bad
// input.
throw new IllegalArgumentException("Invalid unicode character value " + cp);
}
}
}

View File

@ -1,506 +0,0 @@
/* Copyright (c) 2008 Google Inc.
*
* 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.yaml.snakeyaml.external.com.google.gdata.util.common.base;
import java.io.IOException;
/**
* An {@link Escaper} that converts literal text into a format safe for
* inclusion in a particular context (such as an XML document). Typically (but
* not always), the inverse process of "unescaping" the text is performed
* automatically by the relevant parser.
*
* <p>
* For example, an XML escaper would convert the literal string
* {@code "Foo<Bar>"} into {@code "Foo&lt;Bar&gt;"} to prevent {@code "<Bar>"}
* from being confused with an XML tag. When the resulting XML document is
* parsed, the parser API will return this text as the original literal string
* {@code "Foo<Bar>"}.
*
* <p>
* <b>Note:</b> This class is similar to {@link CharEscaper} but with one very
* important difference. A CharEscaper can only process Java <a
* href="http://en.wikipedia.org/wiki/UTF-16">UTF16</a> characters in isolation
* and may not cope when it encounters surrogate pairs. This class facilitates
* the correct escaping of all Unicode characters.
*
* <p>
* As there are important reasons, including potential security issues, to
* handle Unicode correctly if you are considering implementing a new escaper
* you should favor using UnicodeEscaper wherever possible.
*
* <p>
* A {@code UnicodeEscaper} instance is required to be stateless, and safe when
* used concurrently by multiple threads.
*
* <p>
* Several popular escapers are defined as constants in the class
* {@link CharEscapers}. To create your own escapers extend this class and
* implement the {@link #escape(int)} method.
*
*
*/
public abstract class UnicodeEscaper implements Escaper {
/** The amount of padding (chars) to use when growing the escape buffer. */
private static final int DEST_PAD = 32;
/**
* Returns the escaped form of the given Unicode code point, or {@code null}
* if this code point does not need to be escaped. When called as part of an
* escaping operation, the given code point is guaranteed to be in the range
* {@code 0 <= cp <= Character#MAX_CODE_POINT}.
*
* <p>
* If an empty array is returned, this effectively strips the input
* character from the resulting text.
*
* <p>
* If the character does not need to be escaped, this method should return
* {@code null}, rather than an array containing the character
* representation of the code point. This enables the escaping algorithm to
* perform more efficiently.
*
* <p>
* If the implementation of this method cannot correctly handle a particular
* code point then it should either throw an appropriate runtime exception
* or return a suitable replacement character. It must never silently
* discard invalid input as this may constitute a security risk.
*
* @param cp
* the Unicode code point to escape if necessary
* @return the replacement characters, or {@code null} if no escaping was
* needed
*/
protected abstract char[] escape(int cp);
/**
* Scans a sub-sequence of characters from a given {@link CharSequence},
* returning the index of the next character that requires escaping.
*
* <p>
* <b>Note:</b> When implementing an escaper, it is a good idea to override
* this method for efficiency. The base class implementation determines
* successive Unicode code points and invokes {@link #escape(int)} for each
* of them. If the semantics of your escaper are such that code points in
* the supplementary range are either all escaped or all unescaped, this
* method can be implemented more efficiently using
* {@link CharSequence#charAt(int)}.
*
* <p>
* Note however that if your escaper does not escape characters in the
* supplementary range, you should either continue to validate the
* correctness of any surrogate characters encountered or provide a clear
* warning to users that your escaper does not validate its input.
*
* <p>
* See {@link PercentEscaper} for an example.
*
* @param csq
* a sequence of characters
* @param start
* the index of the first character to be scanned
* @param end
* the index immediately after the last character to be scanned
* @throws IllegalArgumentException
* if the scanned sub-sequence of {@code csq} contains invalid
* surrogate pairs
*/
protected int nextEscapeIndex(CharSequence csq, int start, int end) {
int index = start;
while (index < end) {
int cp = codePointAt(csq, index, end);
if (cp < 0 || escape(cp) != null) {
break;
}
index += Character.isSupplementaryCodePoint(cp) ? 2 : 1;
}
return index;
}
/**
* Returns the escaped form of a given literal string.
*
* <p>
* If you are escaping input in arbitrary successive chunks, then it is not
* generally safe to use this method. If an input string ends with an
* unmatched high surrogate character, then this method will throw
* {@link IllegalArgumentException}. You should either ensure your input is
* valid <a href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a> before
* calling this method or use an escaped {@link Appendable} (as returned by
* {@link #escape(Appendable)}) which can cope with arbitrarily split input.
*
* <p>
* <b>Note:</b> When implementing an escaper it is a good idea to override
* this method for efficiency by inlining the implementation of
* {@link #nextEscapeIndex(CharSequence, int, int)} directly. Doing this for
* {@link PercentEscaper} more than doubled the performance for unescaped
* strings (as measured by {@link CharEscapersBenchmark}).
*
* @param string
* the literal string to be escaped
* @return the escaped form of {@code string}
* @throws NullPointerException
* if {@code string} is null
* @throws IllegalArgumentException
* if invalid surrogate characters are encountered
*/
public String escape(String string) {
int end = string.length();
int index = nextEscapeIndex(string, 0, end);
return index == end ? string : escapeSlow(string, index);
}
/**
* Returns the escaped form of a given literal string, starting at the given
* index. This method is called by the {@link #escape(String)} method when
* it discovers that escaping is required. It is protected to allow
* subclasses to override the fastpath escaping function to inline their
* escaping test. See {@link CharEscaperBuilder} for an example usage.
*
* <p>
* This method is not reentrant and may only be invoked by the top level
* {@link #escape(String)} method.
*
* @param s
* the literal string to be escaped
* @param index
* the index to start escaping from
* @return the escaped form of {@code string}
* @throws NullPointerException
* if {@code string} is null
* @throws IllegalArgumentException
* if invalid surrogate characters are encountered
*/
protected final String escapeSlow(String s, int index) {
int end = s.length();
// Get a destination buffer and setup some loop variables.
char[] dest = DEST_TL.get();
int destIndex = 0;
int unescapedChunkStart = 0;
while (index < end) {
int cp = codePointAt(s, index, end);
if (cp < 0) {
throw new IllegalArgumentException("Trailing high surrogate at end of input");
}
char[] escaped = escape(cp);
if (escaped != null) {
int charsSkipped = index - unescapedChunkStart;
// This is the size needed to add the replacement, not the full
// size needed by the string. We only regrow when we absolutely
// must.
int sizeNeeded = destIndex + charsSkipped + escaped.length;
if (dest.length < sizeNeeded) {
int destLength = sizeNeeded + (end - index) + DEST_PAD;
dest = growBuffer(dest, destIndex, destLength);
}
// If we have skipped any characters, we need to copy them now.
if (charsSkipped > 0) {
s.getChars(unescapedChunkStart, index, dest, destIndex);
destIndex += charsSkipped;
}
if (escaped.length > 0) {
System.arraycopy(escaped, 0, dest, destIndex, escaped.length);
destIndex += escaped.length;
}
}
unescapedChunkStart = index + (Character.isSupplementaryCodePoint(cp) ? 2 : 1);
index = nextEscapeIndex(s, unescapedChunkStart, end);
}
// Process trailing unescaped characters - no need to account for
// escaped
// length or padding the allocation.
int charsSkipped = end - unescapedChunkStart;
if (charsSkipped > 0) {
int endIndex = destIndex + charsSkipped;
if (dest.length < endIndex) {
dest = growBuffer(dest, destIndex, endIndex);
}
s.getChars(unescapedChunkStart, end, dest, destIndex);
destIndex = endIndex;
}
return new String(dest, 0, destIndex);
}
/**
* Returns an {@code Appendable} instance which automatically escapes all
* text appended to it before passing the resulting text to an underlying
* {@code Appendable}.
*
* <p>
* Unlike {@link #escape(String)} it is permitted to append arbitrarily
* split input to this Appendable, including input that is split over a
* surrogate pair. In this case the pending high surrogate character will
* not be processed until the corresponding low surrogate is appended. This
* means that a trailing high surrogate character at the end of the input
* cannot be detected and will be silently ignored. This is unavoidable
* since the Appendable interface has no {@code close()} method, and it is
* impossible to determine when the last characters have been appended.
*
* <p>
* The methods of the returned object will propagate any exceptions thrown
* by the underlying {@code Appendable}.
*
* <p>
* For well formed <a href="http://en.wikipedia.org/wiki/UTF-16">UTF-16</a>
* the escaping behavior is identical to that of {@link #escape(String)} and
* the following code is equivalent to (but much slower than)
* {@code escaper.escape(string)}:
*
* <pre>
* {
* &#064;code
* StringBuilder sb = new StringBuilder();
* escaper.escape(sb).append(string);
* return sb.toString();
* }
* </pre>
*
* @param out
* the underlying {@code Appendable} to append escaped output to
* @return an {@code Appendable} which passes text to {@code out} after
* escaping it
* @throws NullPointerException
* if {@code out} is null
* @throws IllegalArgumentException
* if invalid surrogate characters are encountered
*
*/
public Appendable escape(final Appendable out) {
assert out != null;
return new Appendable() {
int pendingHighSurrogate = -1;
char[] decodedChars = new char[2];
public Appendable append(CharSequence csq) throws IOException {
return append(csq, 0, csq.length());
}
public Appendable append(CharSequence csq, int start, int end) throws IOException {
int index = start;
if (index < end) {
// This is a little subtle: index must never reference the
// middle of a
// surrogate pair but unescapedChunkStart can. The first
// time we enter
// the loop below it is possible that index !=
// unescapedChunkStart.
int unescapedChunkStart = index;
if (pendingHighSurrogate != -1) {
// Our last append operation ended halfway through a
// surrogate pair
// so we have to do some extra work first.
char c = csq.charAt(index++);
if (!Character.isLowSurrogate(c)) {
throw new IllegalArgumentException(
"Expected low surrogate character but got " + c);
}
char[] escaped = escape(Character.toCodePoint((char) pendingHighSurrogate,
c));
if (escaped != null) {
// Emit the escaped character and adjust
// unescapedChunkStart to
// skip the low surrogate we have consumed.
outputChars(escaped, escaped.length);
unescapedChunkStart += 1;
} else {
// Emit pending high surrogate (unescaped) but do
// not modify
// unescapedChunkStart as we must still emit the low
// surrogate.
out.append((char) pendingHighSurrogate);
}
pendingHighSurrogate = -1;
}
while (true) {
// Find and append the next subsequence of unescaped
// characters.
index = nextEscapeIndex(csq, index, end);
if (index > unescapedChunkStart) {
out.append(csq, unescapedChunkStart, index);
}
if (index == end) {
break;
}
// If we are not finished, calculate the next code
// point.
int cp = codePointAt(csq, index, end);
if (cp < 0) {
// Our sequence ended half way through a surrogate
// pair so just
// record the state and exit.
pendingHighSurrogate = -cp;
break;
}
// Escape the code point and output the characters.
char[] escaped = escape(cp);
if (escaped != null) {
outputChars(escaped, escaped.length);
} else {
// This shouldn't really happen if nextEscapeIndex
// is correct but
// we should cope with false positives.
int len = Character.toChars(cp, decodedChars, 0);
outputChars(decodedChars, len);
}
// Update our index past the escaped character and
// continue.
index += (Character.isSupplementaryCodePoint(cp) ? 2 : 1);
unescapedChunkStart = index;
}
}
return this;
}
public Appendable append(char c) throws IOException {
if (pendingHighSurrogate != -1) {
// Our last append operation ended halfway through a
// surrogate pair
// so we have to do some extra work first.
if (!Character.isLowSurrogate(c)) {
throw new IllegalArgumentException(
"Expected low surrogate character but got '" + c + "' with value "
+ (int) c);
}
char[] escaped = escape(Character.toCodePoint((char) pendingHighSurrogate, c));
if (escaped != null) {
outputChars(escaped, escaped.length);
} else {
out.append((char) pendingHighSurrogate);
out.append(c);
}
pendingHighSurrogate = -1;
} else if (Character.isHighSurrogate(c)) {
// This is the start of a (split) surrogate pair.
pendingHighSurrogate = c;
} else {
if (Character.isLowSurrogate(c)) {
throw new IllegalArgumentException("Unexpected low surrogate character '"
+ c + "' with value " + (int) c);
}
// This is a normal (non surrogate) char.
char[] escaped = escape(c);
if (escaped != null) {
outputChars(escaped, escaped.length);
} else {
out.append(c);
}
}
return this;
}
private void outputChars(char[] chars, int len) throws IOException {
for (int n = 0; n < len; n++) {
out.append(chars[n]);
}
}
};
}
/**
* Returns the Unicode code point of the character at the given index.
*
* <p>
* Unlike {@link Character#codePointAt(CharSequence, int)} or
* {@link String#codePointAt(int)} this method will never fail silently when
* encountering an invalid surrogate pair.
*
* <p>
* The behaviour of this method is as follows:
* <ol>
* <li>If {@code index >= end}, {@link IndexOutOfBoundsException} is thrown.
* <li><b>If the character at the specified index is not a surrogate, it is
* returned.</b>
* <li>If the first character was a high surrogate value, then an attempt is
* made to read the next character.
* <ol>
* <li><b>If the end of the sequence was reached, the negated value of the
* trailing high surrogate is returned.</b>
* <li><b>If the next character was a valid low surrogate, the code point
* value of the high/low surrogate pair is returned.</b>
* <li>If the next character was not a low surrogate value, then
* {@link IllegalArgumentException} is thrown.
* </ol>
* <li>If the first character was a low surrogate value,
* {@link IllegalArgumentException} is thrown.
* </ol>
*
* @param seq
* the sequence of characters from which to decode the code point
* @param index
* the index of the first character to decode
* @param end
* the index beyond the last valid character to decode
* @return the Unicode code point for the given index or the negated value
* of the trailing high surrogate character at the end of the
* sequence
*/
protected static final int codePointAt(CharSequence seq, int index, int end) {
if (index < end) {
char c1 = seq.charAt(index++);
if (c1 < Character.MIN_HIGH_SURROGATE || c1 > Character.MAX_LOW_SURROGATE) {
// Fast path (first test is probably all we need to do)
return c1;
} else if (c1 <= Character.MAX_HIGH_SURROGATE) {
// If the high surrogate was the last character, return its
// inverse
if (index == end) {
return -c1;
}
// Otherwise look for the low surrogate following it
char c2 = seq.charAt(index);
if (Character.isLowSurrogate(c2)) {
return Character.toCodePoint(c1, c2);
}
throw new IllegalArgumentException("Expected low surrogate but got char '" + c2
+ "' with value " + (int) c2 + " at index " + index);
} else {
throw new IllegalArgumentException("Unexpected low surrogate character '" + c1
+ "' with value " + (int) c1 + " at index " + (index - 1));
}
}
throw new IndexOutOfBoundsException("Index exceeds specified range");
}
/**
* Helper method to grow the character buffer as needed, this only happens
* once in a while so it's ok if it's in a method call. If the index passed
* in is 0 then no copying will be done.
*/
private static final char[] growBuffer(char[] dest, int index, int size) {
char[] copy = new char[size];
if (index > 0) {
System.arraycopy(dest, 0, copy, 0, index);
}
return copy;
}
/**
* A thread-local destination buffer to keep us from creating new buffers.
* The starting size is 1024 characters. If we grow past this we don't put
* it back in the threadlocal, we just keep going and grow as needed.
*/
private static final ThreadLocal<char[]> DEST_TL = new ThreadLocal<char[]>() {
@Override
protected char[] initialValue() {
return new char[1024];
}
};
}

View File

@ -1,30 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
/**
* Control instance variables.
*/
public enum BeanAccess {
/** use JavaBean properties and public fields */
DEFAULT,
/** use all declared fields (including inherited) */
FIELD,
/** reserved */
PROPERTY;
}

View File

@ -1,52 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
import java.lang.reflect.Field;
import org.yaml.snakeyaml.error.YAMLException;
/**
* <p>
* A <code>FieldProperty</code> is a <code>Property</code> which is accessed as
* a field, without going through accessor methods (setX, getX). The field may
* have any scope (public, package, protected, private).
* </p>
*/
public class FieldProperty extends GenericProperty {
private final Field field;
public FieldProperty(Field field) {
super(field.getName(), field.getType(), field.getGenericType());
this.field = field;
field.setAccessible(true);
}
@Override
public void set(Object object, Object value) throws Exception {
field.set(object, value);
}
@Override
public Object get(Object object) {
try {
return field.get(object);
} catch (Exception e) {
throw new YAMLException("Unable to access field " + field.getName() + " on object "
+ object + " : " + e);
}
}
}

View File

@ -1,82 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
abstract public class GenericProperty extends Property {
private Type genType;
public GenericProperty(String name, Class<?> aClass, Type aType) {
super(name, aClass);
genType = aType;
actualClassesChecked = aType == null;
}
private boolean actualClassesChecked;
private Class<?>[] actualClasses;
public Class<?>[] getActualTypeArguments() { // should we synchronize here ?
if (!actualClassesChecked) {
if (genType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0) {
actualClasses = new Class<?>[actualTypeArguments.length];
for (int i = 0; i < actualTypeArguments.length; i++) {
if (actualTypeArguments[i] instanceof Class<?>) {
actualClasses[i] = (Class<?>) actualTypeArguments[i];
} else if (actualTypeArguments[i] instanceof ParameterizedType) {
actualClasses[i] = (Class<?>) ((ParameterizedType) actualTypeArguments[i])
.getRawType();
} else if (actualTypeArguments[i] instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) actualTypeArguments[i])
.getGenericComponentType();
if (componentType instanceof Class<?>) {
actualClasses[i] = Array.newInstance((Class<?>) componentType, 0)
.getClass();
} else {
actualClasses = null;
break;
}
} else {
actualClasses = null;
break;
}
}
}
} else if (genType instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) genType).getGenericComponentType();
if (componentType instanceof Class<?>) {
actualClasses = new Class<?>[] { (Class<?>) componentType };
}
} else if (genType instanceof Class<?>) {// XXX this check is only
// required for IcedTea6
Class<?> classType = (Class<?>) genType;
if (classType.isArray()) {
actualClasses = new Class<?>[1];
actualClasses[0] = getType().getComponentType();
}
}
actualClassesChecked = true;
}
return actualClasses;
}
}

View File

@ -1,71 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
import java.beans.PropertyDescriptor;
import org.yaml.snakeyaml.error.YAMLException;
/**
* <p>
* A <code>MethodProperty</code> is a <code>Property</code> which is accessed
* through accessor methods (setX, getX). It is possible to have a
* <code>MethodProperty</code> which has only setter, only getter, or both. It
* is not possible to have a <code>MethodProperty</code> which has neither
* setter nor getter.
* </p>
*/
public class MethodProperty extends GenericProperty {
private final PropertyDescriptor property;
private final boolean readable;
private final boolean writable;
public MethodProperty(PropertyDescriptor property) {
super(property.getName(), property.getPropertyType(),
property.getReadMethod() == null ? null : property.getReadMethod()
.getGenericReturnType());
this.property = property;
this.readable = property.getReadMethod() != null;
this.writable = property.getWriteMethod() != null;
}
@Override
public void set(Object object, Object value) throws Exception {
property.getWriteMethod().invoke(object, value);
}
@Override
public Object get(Object object) {
try {
property.getReadMethod().setAccessible(true);// issue 50
return property.getReadMethod().invoke(object);
} catch (Exception e) {
throw new YAMLException("Unable to find getter for property '" + property.getName()
+ "' on object " + object + ":" + e);
}
}
@Override
public boolean isWritable() {
return writable;
}
@Override
public boolean isReadable() {
return readable;
}
}

View File

@ -1,44 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
/**
* A property that does not map to a real property; this is used when {@link
* PropertyUtils}.setSkipMissingProperties(boolean) is set to true.
*/
public class MissingProperty extends Property {
public MissingProperty(String name) {
super(name, Object.class);
}
@Override
public Class<?>[] getActualTypeArguments() {
return new Class[0];
}
/**
* Setter does nothing.
*/
@Override
public void set(Object object, Object value) throws Exception {
}
@Override
public Object get(Object object) {
return object;
}
}

View File

@ -1,85 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
/**
* <p>
* A <code>Property</code> represents a single member variable of a class,
* possibly including its accessor methods (getX, setX). The name stored in this
* class is the actual name of the property as given for the class, not an
* alias.
* </p>
*
* <p>
* Objects of this class have a total ordering which defaults to ordering based
* on the name of the property.
* </p>
*/
public abstract class Property implements Comparable<Property> {
private final String name;
private final Class<?> type;
public Property(String name, Class<?> type) {
this.name = name;
this.type = type;
}
public Class<?> getType() {
return type;
}
abstract public Class<?>[] getActualTypeArguments();
public String getName() {
return name;
}
@Override
public String toString() {
return getName() + " of " + getType();
}
public int compareTo(Property o) {
return name.compareTo(o.name);
}
public boolean isWritable() {
return true;
}
public boolean isReadable() {
return true;
}
abstract public void set(Object object, Object value) throws Exception;
abstract public Object get(Object object);
@Override
public int hashCode() {
return name.hashCode() + type.hashCode();
}
@Override
public boolean equals(Object other) {
if (other instanceof Property) {
Property p = (Property) other;
return name.equals(p.getName()) && type.equals(p.getType());
}
return false;
}
}

View File

@ -1,166 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.introspector;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.yaml.snakeyaml.error.YAMLException;
public class PropertyUtils {
private final Map<Class<?>, Map<String, Property>> propertiesCache = new HashMap<Class<?>, Map<String, Property>>();
private final Map<Class<?>, Set<Property>> readableProperties = new HashMap<Class<?>, Set<Property>>();
private BeanAccess beanAccess = BeanAccess.DEFAULT;
private boolean allowReadOnlyProperties = false;
private boolean skipMissingProperties = false;
protected Map<String, Property> getPropertiesMap(Class<?> type, BeanAccess bAccess)
throws IntrospectionException {
if (propertiesCache.containsKey(type)) {
return propertiesCache.get(type);
}
Map<String, Property> properties = new LinkedHashMap<String, Property>();
boolean inaccessableFieldsExist = false;
switch (bAccess) {
case FIELD:
for (Class<?> c = type; c != null; c = c.getSuperclass()) {
for (Field field : c.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)
&& !properties.containsKey(field.getName())) {
properties.put(field.getName(), new FieldProperty(field));
}
}
}
break;
default:
// add JavaBean properties
for (PropertyDescriptor property : Introspector.getBeanInfo(type)
.getPropertyDescriptors()) {
Method readMethod = property.getReadMethod();
if (readMethod == null || !readMethod.getName().equals("getClass")) {
properties.put(property.getName(), new MethodProperty(property));
}
}
// add public fields
for (Class<?> c = type; c != null; c = c.getSuperclass()) {
for (Field field : c.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
if (Modifier.isPublic(modifiers)) {
properties.put(field.getName(), new FieldProperty(field));
} else {
inaccessableFieldsExist = true;
}
}
}
}
break;
}
if (properties.isEmpty() && inaccessableFieldsExist) {
throw new YAMLException("No JavaBean properties found in " + type.getName());
}
propertiesCache.put(type, properties);
return properties;
}
public Set<Property> getProperties(Class<? extends Object> type) throws IntrospectionException {
return getProperties(type, beanAccess);
}
public Set<Property> getProperties(Class<? extends Object> type, BeanAccess bAccess)
throws IntrospectionException {
if (readableProperties.containsKey(type)) {
return readableProperties.get(type);
}
Set<Property> properties = createPropertySet(type, bAccess);
readableProperties.put(type, properties);
return properties;
}
protected Set<Property> createPropertySet(Class<? extends Object> type, BeanAccess bAccess)
throws IntrospectionException {
Set<Property> properties = new TreeSet<Property>();
Collection<Property> props = getPropertiesMap(type, bAccess).values();
for (Property property : props) {
if (property.isReadable() && (allowReadOnlyProperties || property.isWritable())) {
properties.add(property);
}
}
return properties;
}
public Property getProperty(Class<? extends Object> type, String name)
throws IntrospectionException {
return getProperty(type, name, beanAccess);
}
public Property getProperty(Class<? extends Object> type, String name, BeanAccess bAccess)
throws IntrospectionException {
Map<String, Property> properties = getPropertiesMap(type, bAccess);
Property property = properties.get(name);
if (property == null && skipMissingProperties) {
property = new MissingProperty(name);
}
if (property == null || !property.isWritable()) {
throw new YAMLException("Unable to find property '" + name + "' on class: "
+ type.getName());
}
return property;
}
public void setBeanAccess(BeanAccess beanAccess) {
if (this.beanAccess != beanAccess) {
this.beanAccess = beanAccess;
propertiesCache.clear();
readableProperties.clear();
}
}
public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
if (this.allowReadOnlyProperties != allowReadOnlyProperties) {
this.allowReadOnlyProperties = allowReadOnlyProperties;
readableProperties.clear();
}
}
/**
* Skip properties that are missing during deserialization of YAML to a Java
* object. The default is false.
*
* @param skipMissingProperties
* true if missing properties should be skipped, false otherwise.
*/
public void setSkipMissingProperties(boolean skipMissingProperties) {
if (this.skipMissingProperties != skipMissingProperties) {
this.skipMissingProperties = skipMissingProperties;
readableProperties.clear();
}
}
}

View File

@ -1,35 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
public class AnchorNode extends Node {
private Node realNode;
public AnchorNode(Node realNode) {
super(realNode.getTag(), realNode.getStartMark(), realNode.getEndMark());
this.realNode = realNode;
}
@Override
public NodeId getNodeId() {
return NodeId.anchor;
}
public Node getRealNode() {
return realNode;
}
}

View File

@ -1,49 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
import org.yaml.snakeyaml.error.Mark;
/**
* Base class for the two collection types {@link MappingNode mapping} and
* {@link SequenceNode collection}.
*/
public abstract class CollectionNode extends Node {
private Boolean flowStyle;
public CollectionNode(Tag tag, Mark startMark, Mark endMark, Boolean flowStyle) {
super(tag, startMark, endMark);
this.flowStyle = flowStyle;
}
/**
* Serialization style of this collection.
*
* @return <code>true</code> for flow style, <code>false</code> for block
* style.
*/
public Boolean getFlowStyle() {
return flowStyle;
}
public void setFlowStyle(Boolean flowStyle) {
this.flowStyle = flowStyle;
}
public void setEndMark(Mark endMark) {
this.endMark = endMark;
}
}

View File

@ -1,111 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
import java.util.List;
import org.yaml.snakeyaml.error.Mark;
/**
* Represents a map.
* <p>
* A map is a collection of unsorted key-value pairs.
* </p>
*/
public class MappingNode extends CollectionNode {
private List<NodeTuple> value;
private boolean merged = false;
public MappingNode(Tag tag, boolean resolved, List<NodeTuple> value, Mark startMark,
Mark endMark, Boolean flowStyle) {
super(tag, startMark, endMark, flowStyle);
if (value == null) {
throw new NullPointerException("value in a Node is required.");
}
this.value = value;
this.resolved = resolved;
}
public MappingNode(Tag tag, List<NodeTuple> value, Boolean flowStyle) {
this(tag, true, value, null, null, flowStyle);
}
@Override
public NodeId getNodeId() {
return NodeId.mapping;
}
/**
* Returns the entries of this map.
*
* @return List of entries.
*/
public List<NodeTuple> getValue() {
return value;
}
public void setValue(List<NodeTuple> merge) {
value = merge;
}
public void setOnlyKeyType(Class<? extends Object> keyType) {
for (NodeTuple nodes : value) {
nodes.getKeyNode().setType(keyType);
}
}
public void setTypes(Class<? extends Object> keyType, Class<? extends Object> valueType) {
for (NodeTuple nodes : value) {
nodes.getValueNode().setType(valueType);
nodes.getKeyNode().setType(keyType);
}
}
@Override
public String toString() {
String values;
StringBuilder buf = new StringBuilder();
for (NodeTuple node : getValue()) {
buf.append("{ key=");
buf.append(node.getKeyNode());
buf.append("; value=");
if (node.getValueNode() instanceof CollectionNode) {
// to avoid overflow in case of recursive structures
buf.append(System.identityHashCode(node.getValueNode()));
} else {
buf.append(node.toString());
}
buf.append(" }");
}
values = buf.toString();
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", values=" + values + ")>";
}
/**
* @param merged
* - true if map contains merge node
*/
public void setMerged(boolean merged) {
this.merged = merged;
}
/**
* @return true if map contains merge node
*/
public boolean isMerged() {
return merged;
}
}

View File

@ -1,166 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
import org.yaml.snakeyaml.error.Mark;
/**
* Base class for all nodes.
* <p>
* The nodes form the node-graph described in the <a
* href="http://yaml.org/spec/1.1/">YAML Specification</a>.
* </p>
* <p>
* While loading, the node graph is usually created by the
* {@link org.yaml.snakeyaml.composer.Composer}, and later transformed into
* application specific Java classes by the classes from the
* {@link org.yaml.snakeyaml.constructor} package.
* </p>
*/
public abstract class Node {
private Tag tag;
private Mark startMark;
protected Mark endMark;
private Class<? extends Object> type;
private boolean twoStepsConstruction;
/**
* true when the tag is assigned by the resolver
*/
protected boolean resolved;
protected Boolean useClassConstructor;
public Node(Tag tag, Mark startMark, Mark endMark) {
setTag(tag);
this.startMark = startMark;
this.endMark = endMark;
this.type = Object.class;
this.twoStepsConstruction = false;
this.resolved = true;
this.useClassConstructor = null;
}
/**
* Tag of this node.
* <p>
* Every node has a tag assigned. The tag is either local or global.
*
* @return Tag of this node.
*/
public Tag getTag() {
return this.tag;
}
public Mark getEndMark() {
return endMark;
}
/**
* For error reporting.
*
* @see "class variable 'id' in PyYAML"
* @return scalar, sequence, mapping
*/
public abstract NodeId getNodeId();
public Mark getStartMark() {
return startMark;
}
public void setTag(Tag tag) {
if (tag == null) {
throw new NullPointerException("tag in a Node is required.");
}
this.tag = tag;
}
/**
* Two Nodes are never equal.
*/
@Override
public final boolean equals(Object obj) {
return super.equals(obj);
}
public Class<? extends Object> getType() {
return type;
}
public void setType(Class<? extends Object> type) {
if (!type.isAssignableFrom(this.type)) {
this.type = type;
}
}
public void setTwoStepsConstruction(boolean twoStepsConstruction) {
this.twoStepsConstruction = twoStepsConstruction;
}
/**
* Indicates if this node must be constructed in two steps.
* <p>
* Two-step construction is required whenever a node is a child (direct or
* indirect) of it self. That is, if a recursive structure is build using
* anchors and aliases.
* </p>
* <p>
* Set by {@link org.yaml.snakeyaml.composer.Composer}, used during the
* construction process.
* </p>
* <p>
* Only relevant during loading.
* </p>
*
* @return <code>true</code> if the node is self referenced.
*/
public boolean isTwoStepsConstruction() {
return twoStepsConstruction;
}
@Override
public final int hashCode() {
return super.hashCode();
}
public boolean useClassConstructor() {
if (useClassConstructor == null) {
if (!tag.isSecondary() && isResolved() && !Object.class.equals(type)
&& !tag.equals(Tag.NULL)) {
return true;
} else if (tag.isCompatible(getType())) {
// the tag is compatible with the runtime class
// the tag will be ignored
return true;
} else {
return false;
}
}
return useClassConstructor.booleanValue();
}
public void setUseClassConstructor(Boolean useClassConstructor) {
this.useClassConstructor = useClassConstructor;
}
/**
* Indicates if the tag was added by
* {@link org.yaml.snakeyaml.resolver.Resolver}.
*
* @return <code>true</code> if the tag of this node was resolved
*/
public boolean isResolved() {
return resolved;
}
}

View File

@ -1,23 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
/**
* Enum for the three basic YAML types: scalar, sequence and mapping.
*/
public enum NodeId {
scalar, sequence, mapping, anchor;
}

View File

@ -1,57 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
/**
* Stores one key value pair used in a map.
*/
public final class NodeTuple {
private Node keyNode;
private Node valueNode;
public NodeTuple(Node keyNode, Node valueNode) {
if (keyNode == null || valueNode == null) {
throw new NullPointerException("Nodes must be provided.");
}
this.keyNode = keyNode;
this.valueNode = valueNode;
}
/**
* Key node.
*
* @return the node used as key
*/
public Node getKeyNode() {
return keyNode;
}
/**
* Value node.
*
* @return node used as value
*/
public Node getValueNode() {
return valueNode;
}
@Override
public String toString() {
return "<NodeTuple keyNode=" + keyNode.toString() + "; valueNode=" + valueNode.toString()
+ ">";
}
}

View File

@ -1,75 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
import org.yaml.snakeyaml.error.Mark;
/**
* Represents a scalar node.
* <p>
* Scalar nodes form the leaves in the node graph.
* </p>
*/
public class ScalarNode extends Node {
private Character style;
private String value;
public ScalarNode(Tag tag, String value, Mark startMark, Mark endMark, Character style) {
this(tag, true, value, startMark, endMark, style);
}
public ScalarNode(Tag tag, boolean resolved, String value, Mark startMark, Mark endMark,
Character style) {
super(tag, startMark, endMark);
if (value == null) {
throw new NullPointerException("value in a Node is required.");
}
this.value = value;
this.style = style;
this.resolved = resolved;
}
/**
* Get scalar style of this node.
*
* @see org.yaml.snakeyaml.events.ScalarEvent
* @see <a href="http://yaml.org/spec/1.1/#id903915">Chapter 9. Scalar
* Styles</a>
* @return style of this scalar node
*/
public Character getStyle() {
return style;
}
@Override
public NodeId getNodeId() {
return NodeId.scalar;
}
/**
* Value of this scalar.
*
* @return Scalar's value.
*/
public String getValue() {
return value;
}
public String toString() {
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", value=" + getValue()
+ ")>";
}
}

View File

@ -1,69 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
import java.util.List;
import org.yaml.snakeyaml.error.Mark;
/**
* Represents a sequence.
* <p>
* A sequence is a ordered collection of nodes.
* </p>
*/
public class SequenceNode extends CollectionNode {
final private List<Node> value;
public SequenceNode(Tag tag, boolean resolved, List<Node> value, Mark startMark, Mark endMark,
Boolean flowStyle) {
super(tag, startMark, endMark, flowStyle);
if (value == null) {
throw new NullPointerException("value in a Node is required.");
}
this.value = value;
this.resolved = resolved;
}
public SequenceNode(Tag tag, List<Node> value, Boolean flowStyle) {
this(tag, true, value, null, null, flowStyle);
}
@Override
public NodeId getNodeId() {
return NodeId.sequence;
}
/**
* Returns the elements in this sequence.
*
* @return Nodes in the specified order.
*/
public List<Node> getValue() {
return value;
}
public void setListType(Class<? extends Object> listType) {
for (Node node : value) {
node.setType(listType);
}
}
public String toString() {
return "<" + this.getClass().getName() + " (tag=" + getTag() + ", value=" + getValue()
+ ")>";
}
}

View File

@ -1,171 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.nodes;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.util.UriEncoder;
public final class Tag implements Comparable<Tag> {
public static final String PREFIX = "tag:yaml.org,2002:";
public static final Tag YAML = new Tag(PREFIX + "yaml");
public static final Tag MERGE = new Tag(PREFIX + "merge");
public static final Tag SET = new Tag(PREFIX + "set");
public static final Tag PAIRS = new Tag(PREFIX + "pairs");
public static final Tag OMAP = new Tag(PREFIX + "omap");
public static final Tag BINARY = new Tag(PREFIX + "binary");
public static final Tag INT = new Tag(PREFIX + "int");
public static final Tag FLOAT = new Tag(PREFIX + "float");
public static final Tag TIMESTAMP = new Tag(PREFIX + "timestamp");
public static final Tag BOOL = new Tag(PREFIX + "bool");
public static final Tag NULL = new Tag(PREFIX + "null");
public static final Tag STR = new Tag(PREFIX + "str");
public static final Tag SEQ = new Tag(PREFIX + "seq");
public static final Tag MAP = new Tag(PREFIX + "map");
public static final Map<Tag, Set<Class<?>>> COMPATIBILITY_MAP;
static {
COMPATIBILITY_MAP = new HashMap<Tag, Set<Class<?>>>();
Set<Class<?>> floatSet = new HashSet<Class<?>>();
floatSet.add(Double.class);
floatSet.add(Float.class);
floatSet.add(BigDecimal.class);
COMPATIBILITY_MAP.put(FLOAT, floatSet);
//
Set<Class<?>> intSet = new HashSet<Class<?>>();
intSet.add(Integer.class);
intSet.add(Long.class);
intSet.add(BigInteger.class);
COMPATIBILITY_MAP.put(INT, intSet);
//
Set<Class<?>> timestampSet = new HashSet<Class<?>>();
timestampSet.add(Date.class);
timestampSet.add(java.sql.Date.class);
timestampSet.add(Timestamp.class);
COMPATIBILITY_MAP.put(TIMESTAMP, timestampSet);
}
private final String value;
private boolean secondary = false; // see http://www.yaml.org/refcard.html
public Tag(String tag) {
if (tag == null) {
throw new NullPointerException("Tag must be provided.");
} else if (tag.length() == 0) {
throw new IllegalArgumentException("Tag must not be empty.");
} else if (tag.trim().length() != tag.length()) {
throw new IllegalArgumentException("Tag must not contain leading or trailing spaces.");
}
this.value = UriEncoder.encode(tag);
this.secondary = !tag.startsWith(PREFIX);
}
public Tag(Class<? extends Object> clazz) {
if (clazz == null) {
throw new NullPointerException("Class for tag must be provided.");
}
this.value = Tag.PREFIX + UriEncoder.encode(clazz.getName());
}
public Tag(URI uri) {
if (uri == null) {
throw new NullPointerException("URI for tag must be provided.");
}
this.value = uri.toASCIIString();
}
public boolean isSecondary() {
return secondary;
}
public String getValue() {
return value;
}
public boolean startsWith(String prefix) {
return value.startsWith(prefix);
}
public String getClassName() {
if (!value.startsWith(Tag.PREFIX)) {
throw new YAMLException("Invalid tag: " + value);
}
return UriEncoder.decode(value.substring(Tag.PREFIX.length()));
}
public int getLength() {
return value.length();
}
@Override
public String toString() {
return value;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Tag) {
return value.equals(((Tag) obj).getValue());
} else
return false;
}
@Override
public int hashCode() {
return value.hashCode();
}
/**
* Java has more then 1 class compatible with a language-independent tag
* (!!int, !!float, !!timestamp etc)
*
* @param clazz
* - Class to check compatibility
* @return true when the Class can be represented by this
* language-independent tag
*/
public boolean isCompatible(Class<?> clazz) {
Set<Class<?>> set = COMPATIBILITY_MAP.get(this);
if (set != null) {
return set.contains(clazz);
} else {
return false;
}
}
/**
* Check whether this tag matches the global tag for the Class
*
* @param clazz
* - Class to check
* @return true when the this tag can be used as a global tag for the Class
*/
public boolean matches(Class<? extends Object> clazz) {
return value.equals(Tag.PREFIX + clazz.getName());
}
public int compareTo(Tag o) {
return value.compareTo(o.getValue());
}
}

View File

@ -1,65 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.parser;
import org.yaml.snakeyaml.events.Event;
/**
* This interface represents an input stream of {@link Event Events}.
* <p>
* The parser and the scanner form together the 'Parse' step in the loading
* process (see chapter 3.1 of the <a href="http://yaml.org/spec/1.1/">YAML
* Specification</a>).
* </p>
*
* @see org.yaml.snakeyaml.events.Event
*/
public interface Parser {
/**
* Check if the next event is one of the given type.
*
* @param choice
* Event ID.
* @return <code>true</code> if the next event can be assigned to a variable
* of the given type. Returns <code>false</code> if no more events
* are available.
* @throws ParserException
* Thrown in case of malformed input.
*/
public boolean checkEvent(Event.ID choice);
/**
* Return the next event, but do not delete it from the stream.
*
* @return The event that will be returned on the next call to
* {@link #getEvent}
* @throws ParserException
* Thrown in case of malformed input.
*/
public Event peekEvent();
/**
* Returns the next event.
* <p>
* The event will be removed from the stream.
* </p>
* @return the next parsed event
* @throws ParserException
* Thrown in case of malformed input.
*/
public Event getEvent();
}

View File

@ -1,44 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.parser;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.error.MarkedYAMLException;
/**
* Exception thrown by the {@link Parser} implementations in case of malformed
* input.
*/
public class ParserException extends MarkedYAMLException {
private static final long serialVersionUID = -2349253802798398038L;
/**
* Constructs an instance.
*
* @param context
* Part of the input document in which vicinity the problem
* occurred.
* @param contextMark
* Position of the <code>context</code> within the document.
* @param problem
* Part of the input document that caused the problem.
* @param problemMark
* Position of the <code>problem</code>. within the document.
*/
public ParserException(String context, Mark contextMark, String problem, Mark problemMark) {
super(context, contextMark, problem, problemMark, null, null);
}
}

View File

@ -1,794 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.parser;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions.Version;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.events.AliasEvent;
import org.yaml.snakeyaml.events.DocumentEndEvent;
import org.yaml.snakeyaml.events.DocumentStartEvent;
import org.yaml.snakeyaml.events.Event;
import org.yaml.snakeyaml.events.ImplicitTuple;
import org.yaml.snakeyaml.events.MappingEndEvent;
import org.yaml.snakeyaml.events.MappingStartEvent;
import org.yaml.snakeyaml.events.ScalarEvent;
import org.yaml.snakeyaml.events.SequenceEndEvent;
import org.yaml.snakeyaml.events.SequenceStartEvent;
import org.yaml.snakeyaml.events.StreamEndEvent;
import org.yaml.snakeyaml.events.StreamStartEvent;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.reader.StreamReader;
import org.yaml.snakeyaml.scanner.Scanner;
import org.yaml.snakeyaml.scanner.ScannerImpl;
import org.yaml.snakeyaml.tokens.AliasToken;
import org.yaml.snakeyaml.tokens.AnchorToken;
import org.yaml.snakeyaml.tokens.BlockEntryToken;
import org.yaml.snakeyaml.tokens.DirectiveToken;
import org.yaml.snakeyaml.tokens.ScalarToken;
import org.yaml.snakeyaml.tokens.StreamEndToken;
import org.yaml.snakeyaml.tokens.StreamStartToken;
import org.yaml.snakeyaml.tokens.TagToken;
import org.yaml.snakeyaml.tokens.TagTuple;
import org.yaml.snakeyaml.tokens.Token;
import org.yaml.snakeyaml.util.ArrayStack;
/**
* <pre>
* # The following YAML grammar is LL(1) and is parsed by a recursive descent
* parser.
* stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
* implicit_document ::= block_node DOCUMENT-END*
* explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
* block_node_or_indentless_sequence ::=
* ALIAS
* | properties (block_content | indentless_block_sequence)?
* | block_content
* | indentless_block_sequence
* block_node ::= ALIAS
* | properties block_content?
* | block_content
* flow_node ::= ALIAS
* | properties flow_content?
* | flow_content
* properties ::= TAG ANCHOR? | ANCHOR TAG?
* block_content ::= block_collection | flow_collection | SCALAR
* flow_content ::= flow_collection | SCALAR
* block_collection ::= block_sequence | block_mapping
* flow_collection ::= flow_sequence | flow_mapping
* block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
* indentless_sequence ::= (BLOCK-ENTRY block_node?)+
* block_mapping ::= BLOCK-MAPPING_START
* ((KEY block_node_or_indentless_sequence?)?
* (VALUE block_node_or_indentless_sequence?)?)*
* BLOCK-END
* flow_sequence ::= FLOW-SEQUENCE-START
* (flow_sequence_entry FLOW-ENTRY)*
* flow_sequence_entry?
* FLOW-SEQUENCE-END
* flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
* flow_mapping ::= FLOW-MAPPING-START
* (flow_mapping_entry FLOW-ENTRY)*
* flow_mapping_entry?
* FLOW-MAPPING-END
* flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
* FIRST sets:
* stream: { STREAM-START }
* explicit_document: { DIRECTIVE DOCUMENT-START }
* implicit_document: FIRST(block_node)
* block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START }
* flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START }
* block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
* flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
* block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START }
* flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
* block_sequence: { BLOCK-SEQUENCE-START }
* block_mapping: { BLOCK-MAPPING-START }
* block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY }
* indentless_sequence: { ENTRY }
* flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
* flow_sequence: { FLOW-SEQUENCE-START }
* flow_mapping: { FLOW-MAPPING-START }
* flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
* flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
* </pre>
*
* Since writing a recursive-descendant parser is a straightforward task, we do
* not give many comments here.
*/
public class ParserImpl implements Parser {
private static final Map<String, String> DEFAULT_TAGS = new HashMap<String, String>();
static {
DEFAULT_TAGS.put("!", "!");
DEFAULT_TAGS.put("!!", Tag.PREFIX);
}
protected final Scanner scanner;
private Event currentEvent;
private final ArrayStack<Production> states;
private final ArrayStack<Mark> marks;
private Production state;
private VersionTagsTuple directives;
public ParserImpl(StreamReader reader) {
this(new ScannerImpl(reader));
}
public ParserImpl(Scanner scanner) {
this.scanner = scanner;
currentEvent = null;
directives = new VersionTagsTuple(null, new HashMap<String, String>(DEFAULT_TAGS));
states = new ArrayStack<Production>(100);
marks = new ArrayStack<Mark>(10);
state = new ParseStreamStart();
}
/**
* Check the type of the next event.
*/
public boolean checkEvent(Event.ID choice) {
peekEvent();
return currentEvent != null && currentEvent.is(choice);
}
/**
* Get the next event.
*/
public Event peekEvent() {
if (currentEvent == null) {
if (state != null) {
currentEvent = state.produce();
}
}
return currentEvent;
}
/**
* Get the next event and proceed further.
*/
public Event getEvent() {
peekEvent();
Event value = currentEvent;
currentEvent = null;
return value;
}
/**
* <pre>
* stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
* implicit_document ::= block_node DOCUMENT-END*
* explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
* </pre>
*/
private class ParseStreamStart implements Production {
public Event produce() {
// Parse the stream start.
StreamStartToken token = (StreamStartToken) scanner.getToken();
Event event = new StreamStartEvent(token.getStartMark(), token.getEndMark());
// Prepare the next state.
state = new ParseImplicitDocumentStart();
return event;
}
}
private class ParseImplicitDocumentStart implements Production {
public Event produce() {
// Parse an implicit document.
if (!scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart, Token.ID.StreamEnd)) {
directives = new VersionTagsTuple(null, DEFAULT_TAGS);
Token token = scanner.peekToken();
Mark startMark = token.getStartMark();
Mark endMark = startMark;
Event event = new DocumentStartEvent(startMark, endMark, false, null, null);
// Prepare the next state.
states.push(new ParseDocumentEnd());
state = new ParseBlockNode();
return event;
} else {
Production p = new ParseDocumentStart();
return p.produce();
}
}
}
private class ParseDocumentStart implements Production {
public Event produce() {
// Parse any extra document end indicators.
while (scanner.checkToken(Token.ID.DocumentEnd)) {
scanner.getToken();
}
// Parse an explicit document.
Event event;
if (!scanner.checkToken(Token.ID.StreamEnd)) {
Token token = scanner.peekToken();
Mark startMark = token.getStartMark();
VersionTagsTuple tuple = processDirectives();
if (!scanner.checkToken(Token.ID.DocumentStart)) {
throw new ParserException(null, null, "expected '<document start>', but found "
+ scanner.peekToken().getTokenId(), scanner.peekToken().getStartMark());
}
token = scanner.getToken();
Mark endMark = token.getEndMark();
event = new DocumentStartEvent(startMark, endMark, true, tuple.getVersion(),
tuple.getTags());
states.push(new ParseDocumentEnd());
state = new ParseDocumentContent();
} else {
// Parse the end of the stream.
StreamEndToken token = (StreamEndToken) scanner.getToken();
event = new StreamEndEvent(token.getStartMark(), token.getEndMark());
if (!states.isEmpty()) {
throw new YAMLException("Unexpected end of stream. States left: " + states);
}
if (!marks.isEmpty()) {
throw new YAMLException("Unexpected end of stream. Marks left: " + marks);
}
state = null;
}
return event;
}
}
private class ParseDocumentEnd implements Production {
public Event produce() {
// Parse the document end.
Token token = scanner.peekToken();
Mark startMark = token.getStartMark();
Mark endMark = startMark;
boolean explicit = false;
if (scanner.checkToken(Token.ID.DocumentEnd)) {
token = scanner.getToken();
endMark = token.getEndMark();
explicit = true;
}
Event event = new DocumentEndEvent(startMark, endMark, explicit);
// Prepare the next state.
state = new ParseDocumentStart();
return event;
}
}
private class ParseDocumentContent implements Production {
public Event produce() {
Event event;
if (scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart,
Token.ID.DocumentEnd, Token.ID.StreamEnd)) {
event = processEmptyScalar(scanner.peekToken().getStartMark());
state = states.pop();
return event;
} else {
Production p = new ParseBlockNode();
return p.produce();
}
}
}
@SuppressWarnings("unchecked")
private VersionTagsTuple processDirectives() {
Version yamlVersion = null;
HashMap<String, String> tagHandles = new HashMap<String, String>();
while (scanner.checkToken(Token.ID.Directive)) {
@SuppressWarnings("rawtypes")
DirectiveToken token = (DirectiveToken) scanner.getToken();
if (token.getName().equals("YAML")) {
if (yamlVersion != null) {
throw new ParserException(null, null, "found duplicate YAML directive",
token.getStartMark());
}
List<Integer> value = (List<Integer>) token.getValue();
Integer major = value.get(0);
if (major != 1) {
throw new ParserException(null, null,
"found incompatible YAML document (version 1.* is required)",
token.getStartMark());
}
Integer minor = value.get(1);
switch (minor) {
case 0:
yamlVersion = Version.V1_0;
break;
default:
yamlVersion = Version.V1_1;
break;
}
} else if (token.getName().equals("TAG")) {
List<String> value = (List<String>) token.getValue();
String handle = value.get(0);
String prefix = value.get(1);
if (tagHandles.containsKey(handle)) {
throw new ParserException(null, null, "duplicate tag handle " + handle,
token.getStartMark());
}
tagHandles.put(handle, prefix);
}
}
if (yamlVersion != null || !tagHandles.isEmpty()) {
// directives in the document found - drop the previous
for (String key : DEFAULT_TAGS.keySet()) {
// do not overwrite re-defined tags
if (!tagHandles.containsKey(key)) {
tagHandles.put(key, DEFAULT_TAGS.get(key));
}
}
directives = new VersionTagsTuple(yamlVersion, tagHandles);
}
return directives;
}
/**
* <pre>
* block_node_or_indentless_sequence ::= ALIAS
* | properties (block_content | indentless_block_sequence)?
* | block_content
* | indentless_block_sequence
* block_node ::= ALIAS
* | properties block_content?
* | block_content
* flow_node ::= ALIAS
* | properties flow_content?
* | flow_content
* properties ::= TAG ANCHOR? | ANCHOR TAG?
* block_content ::= block_collection | flow_collection | SCALAR
* flow_content ::= flow_collection | SCALAR
* block_collection ::= block_sequence | block_mapping
* flow_collection ::= flow_sequence | flow_mapping
* </pre>
*/
private class ParseBlockNode implements Production {
public Event produce() {
return parseNode(true, false);
}
}
private Event parseFlowNode() {
return parseNode(false, false);
}
private Event parseBlockNodeOrIndentlessSequence() {
return parseNode(true, true);
}
private Event parseNode(boolean block, boolean indentlessSequence) {
Event event;
Mark startMark = null;
Mark endMark = null;
Mark tagMark = null;
if (scanner.checkToken(Token.ID.Alias)) {
AliasToken token = (AliasToken) scanner.getToken();
event = new AliasEvent(token.getValue(), token.getStartMark(), token.getEndMark());
state = states.pop();
} else {
String anchor = null;
TagTuple tagTokenTag = null;
if (scanner.checkToken(Token.ID.Anchor)) {
AnchorToken token = (AnchorToken) scanner.getToken();
startMark = token.getStartMark();
endMark = token.getEndMark();
anchor = token.getValue();
if (scanner.checkToken(Token.ID.Tag)) {
TagToken tagToken = (TagToken) scanner.getToken();
tagMark = tagToken.getStartMark();
endMark = tagToken.getEndMark();
tagTokenTag = tagToken.getValue();
}
} else if (scanner.checkToken(Token.ID.Tag)) {
TagToken tagToken = (TagToken) scanner.getToken();
startMark = tagToken.getStartMark();
tagMark = startMark;
endMark = tagToken.getEndMark();
tagTokenTag = tagToken.getValue();
if (scanner.checkToken(Token.ID.Anchor)) {
AnchorToken token = (AnchorToken) scanner.getToken();
endMark = token.getEndMark();
anchor = token.getValue();
}
}
String tag = null;
if (tagTokenTag != null) {
String handle = tagTokenTag.getHandle();
String suffix = tagTokenTag.getSuffix();
if (handle != null) {
if (!directives.getTags().containsKey(handle)) {
throw new ParserException("while parsing a node", startMark,
"found undefined tag handle " + handle, tagMark);
}
tag = directives.getTags().get(handle) + suffix;
} else {
tag = suffix;
}
}
if (startMark == null) {
startMark = scanner.peekToken().getStartMark();
endMark = startMark;
}
event = null;
boolean implicit = tag == null || tag.equals("!");
if (indentlessSequence && scanner.checkToken(Token.ID.BlockEntry)) {
endMark = scanner.peekToken().getEndMark();
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.FALSE);
state = new ParseIndentlessSequenceEntry();
} else {
if (scanner.checkToken(Token.ID.Scalar)) {
ScalarToken token = (ScalarToken) scanner.getToken();
endMark = token.getEndMark();
ImplicitTuple implicitValues;
if ((token.getPlain() && tag == null) || "!".equals(tag)) {
implicitValues = new ImplicitTuple(true, false);
} else if (tag == null) {
implicitValues = new ImplicitTuple(false, true);
} else {
implicitValues = new ImplicitTuple(false, false);
}
event = new ScalarEvent(anchor, tag, implicitValues, token.getValue(),
startMark, endMark, token.getStyle());
state = states.pop();
} else if (scanner.checkToken(Token.ID.FlowSequenceStart)) {
endMark = scanner.peekToken().getEndMark();
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.TRUE);
state = new ParseFlowSequenceFirstEntry();
} else if (scanner.checkToken(Token.ID.FlowMappingStart)) {
endMark = scanner.peekToken().getEndMark();
event = new MappingStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.TRUE);
state = new ParseFlowMappingFirstKey();
} else if (block && scanner.checkToken(Token.ID.BlockSequenceStart)) {
endMark = scanner.peekToken().getStartMark();
event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.FALSE);
state = new ParseBlockSequenceFirstEntry();
} else if (block && scanner.checkToken(Token.ID.BlockMappingStart)) {
endMark = scanner.peekToken().getStartMark();
event = new MappingStartEvent(anchor, tag, implicit, startMark, endMark,
Boolean.FALSE);
state = new ParseBlockMappingFirstKey();
} else if (anchor != null || tag != null) {
// Empty scalars are allowed even if a tag or an anchor is
// specified.
event = new ScalarEvent(anchor, tag, new ImplicitTuple(implicit, false), "",
startMark, endMark, (char) 0);
state = states.pop();
} else {
String node;
if (block) {
node = "block";
} else {
node = "flow";
}
Token token = scanner.peekToken();
throw new ParserException("while parsing a " + node + " node", startMark,
"expected the node content, but found " + token.getTokenId(),
token.getStartMark());
}
}
}
return event;
}
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)*
// BLOCK-END
private class ParseBlockSequenceFirstEntry implements Production {
public Event produce() {
Token token = scanner.getToken();
marks.push(token.getStartMark());
return new ParseBlockSequenceEntry().produce();
}
}
private class ParseBlockSequenceEntry implements Production {
public Event produce() {
if (scanner.checkToken(Token.ID.BlockEntry)) {
BlockEntryToken token = (BlockEntryToken) scanner.getToken();
if (!scanner.checkToken(Token.ID.BlockEntry, Token.ID.BlockEnd)) {
states.push(new ParseBlockSequenceEntry());
return new ParseBlockNode().produce();
} else {
state = new ParseBlockSequenceEntry();
return processEmptyScalar(token.getEndMark());
}
}
if (!scanner.checkToken(Token.ID.BlockEnd)) {
Token token = scanner.peekToken();
throw new ParserException("while parsing a block collection", marks.pop(),
"expected <block end>, but found " + token.getTokenId(),
token.getStartMark());
}
Token token = scanner.getToken();
Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
state = states.pop();
marks.pop();
return event;
}
}
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
private class ParseIndentlessSequenceEntry implements Production {
public Event produce() {
if (scanner.checkToken(Token.ID.BlockEntry)) {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.BlockEntry, Token.ID.Key, Token.ID.Value,
Token.ID.BlockEnd)) {
states.push(new ParseIndentlessSequenceEntry());
return new ParseBlockNode().produce();
} else {
state = new ParseIndentlessSequenceEntry();
return processEmptyScalar(token.getEndMark());
}
}
Token token = scanner.peekToken();
Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
state = states.pop();
return event;
}
}
private class ParseBlockMappingFirstKey implements Production {
public Event produce() {
Token token = scanner.getToken();
marks.push(token.getStartMark());
return new ParseBlockMappingKey().produce();
}
}
private class ParseBlockMappingKey implements Production {
public Event produce() {
if (scanner.checkToken(Token.ID.Key)) {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
states.push(new ParseBlockMappingValue());
return parseBlockNodeOrIndentlessSequence();
} else {
state = new ParseBlockMappingValue();
return processEmptyScalar(token.getEndMark());
}
}
if (!scanner.checkToken(Token.ID.BlockEnd)) {
Token token = scanner.peekToken();
throw new ParserException("while parsing a block mapping", marks.pop(),
"expected <block end>, but found " + token.getTokenId(),
token.getStartMark());
}
Token token = scanner.getToken();
Event event = new MappingEndEvent(token.getStartMark(), token.getEndMark());
state = states.pop();
marks.pop();
return event;
}
}
private class ParseBlockMappingValue implements Production {
public Event produce() {
if (scanner.checkToken(Token.ID.Value)) {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
states.push(new ParseBlockMappingKey());
return parseBlockNodeOrIndentlessSequence();
} else {
state = new ParseBlockMappingKey();
return processEmptyScalar(token.getEndMark());
}
}
state = new ParseBlockMappingKey();
Token token = scanner.peekToken();
return processEmptyScalar(token.getStartMark());
}
}
/**
* <pre>
* flow_sequence ::= FLOW-SEQUENCE-START
* (flow_sequence_entry FLOW-ENTRY)*
* flow_sequence_entry?
* FLOW-SEQUENCE-END
* flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
* Note that while production rules for both flow_sequence_entry and
* flow_mapping_entry are equal, their interpretations are different.
* For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?`
* generate an inline mapping (set syntax).
* </pre>
*/
private class ParseFlowSequenceFirstEntry implements Production {
public Event produce() {
Token token = scanner.getToken();
marks.push(token.getStartMark());
return new ParseFlowSequenceEntry(true).produce();
}
}
private class ParseFlowSequenceEntry implements Production {
private boolean first = false;
public ParseFlowSequenceEntry(boolean first) {
this.first = first;
}
public Event produce() {
if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) {
if (!first) {
if (scanner.checkToken(Token.ID.FlowEntry)) {
scanner.getToken();
} else {
Token token = scanner.peekToken();
throw new ParserException("while parsing a flow sequence", marks.pop(),
"expected ',' or ']', but got " + token.getTokenId(),
token.getStartMark());
}
}
if (scanner.checkToken(Token.ID.Key)) {
Token token = scanner.peekToken();
Event event = new MappingStartEvent(null, null, true, token.getStartMark(),
token.getEndMark(), Boolean.TRUE);
state = new ParseFlowSequenceEntryMappingKey();
return event;
} else if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) {
states.push(new ParseFlowSequenceEntry(false));
return parseFlowNode();
}
}
Token token = scanner.getToken();
Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
state = states.pop();
marks.pop();
return event;
}
}
private class ParseFlowSequenceEntryMappingKey implements Production {
public Event produce() {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.Value, Token.ID.FlowEntry, Token.ID.FlowSequenceEnd)) {
states.push(new ParseFlowSequenceEntryMappingValue());
return parseFlowNode();
} else {
state = new ParseFlowSequenceEntryMappingValue();
return processEmptyScalar(token.getEndMark());
}
}
}
private class ParseFlowSequenceEntryMappingValue implements Production {
public Event produce() {
if (scanner.checkToken(Token.ID.Value)) {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.FlowEntry, Token.ID.FlowSequenceEnd)) {
states.push(new ParseFlowSequenceEntryMappingEnd());
return parseFlowNode();
} else {
state = new ParseFlowSequenceEntryMappingEnd();
return processEmptyScalar(token.getEndMark());
}
} else {
state = new ParseFlowSequenceEntryMappingEnd();
Token token = scanner.peekToken();
return processEmptyScalar(token.getStartMark());
}
}
}
private class ParseFlowSequenceEntryMappingEnd implements Production {
public Event produce() {
state = new ParseFlowSequenceEntry(false);
Token token = scanner.peekToken();
return new MappingEndEvent(token.getStartMark(), token.getEndMark());
}
}
/**
* <pre>
* flow_mapping ::= FLOW-MAPPING-START
* (flow_mapping_entry FLOW-ENTRY)*
* flow_mapping_entry?
* FLOW-MAPPING-END
* flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
* </pre>
*/
private class ParseFlowMappingFirstKey implements Production {
public Event produce() {
Token token = scanner.getToken();
marks.push(token.getStartMark());
return new ParseFlowMappingKey(true).produce();
}
}
private class ParseFlowMappingKey implements Production {
private boolean first = false;
public ParseFlowMappingKey(boolean first) {
this.first = first;
}
public Event produce() {
if (!scanner.checkToken(Token.ID.FlowMappingEnd)) {
if (!first) {
if (scanner.checkToken(Token.ID.FlowEntry)) {
scanner.getToken();
} else {
Token token = scanner.peekToken();
throw new ParserException("while parsing a flow mapping", marks.pop(),
"expected ',' or '}', but got " + token.getTokenId(),
token.getStartMark());
}
}
if (scanner.checkToken(Token.ID.Key)) {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.Value, Token.ID.FlowEntry,
Token.ID.FlowMappingEnd)) {
states.push(new ParseFlowMappingValue());
return parseFlowNode();
} else {
state = new ParseFlowMappingValue();
return processEmptyScalar(token.getEndMark());
}
} else if (!scanner.checkToken(Token.ID.FlowMappingEnd)) {
states.push(new ParseFlowMappingEmptyValue());
return parseFlowNode();
}
}
Token token = scanner.getToken();
Event event = new MappingEndEvent(token.getStartMark(), token.getEndMark());
state = states.pop();
marks.pop();
return event;
}
}
private class ParseFlowMappingValue implements Production {
public Event produce() {
if (scanner.checkToken(Token.ID.Value)) {
Token token = scanner.getToken();
if (!scanner.checkToken(Token.ID.FlowEntry, Token.ID.FlowMappingEnd)) {
states.push(new ParseFlowMappingKey(false));
return parseFlowNode();
} else {
state = new ParseFlowMappingKey(false);
return processEmptyScalar(token.getEndMark());
}
} else {
state = new ParseFlowMappingKey(false);
Token token = scanner.peekToken();
return processEmptyScalar(token.getStartMark());
}
}
}
private class ParseFlowMappingEmptyValue implements Production {
public Event produce() {
state = new ParseFlowMappingKey(false);
return processEmptyScalar(scanner.peekToken().getStartMark());
}
}
/**
* <pre>
* block_mapping ::= BLOCK-MAPPING_START
* ((KEY block_node_or_indentless_sequence?)?
* (VALUE block_node_or_indentless_sequence?)?)*
* BLOCK-END
* </pre>
*/
private Event processEmptyScalar(Mark mark) {
return new ScalarEvent(null, null, new ImplicitTuple(true, false), "", mark, mark, (char) 0);
}
}

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.parser;
import org.yaml.snakeyaml.events.Event;
/**
* Helper for {@link ParserImpl}. A grammar rule to apply given the symbols on
* top of its stack and the next input token
*
* @see <a href="http://en.wikipedia.org/wiki/LL_parser"></a>
*/
interface Production {
Event produce();
}

View File

@ -1,46 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.parser;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions.Version;
/**
* Store the internal state for directives
*/
class VersionTagsTuple {
private Version version;
private Map<String, String> tags;
public VersionTagsTuple(Version version, Map<String, String> tags) {
this.version = version;
this.tags = tags;
}
public Version getVersion() {
return version;
}
public Map<String, String> getTags() {
return tags;
}
@Override
public String toString() {
return String.format("VersionTagsTuple<%s, %s>", version, tags);
}
}

View File

@ -1,52 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.reader;
import org.yaml.snakeyaml.error.YAMLException;
public class ReaderException extends YAMLException {
private static final long serialVersionUID = 8710781187529689083L;
private final String name;
private final int codePoint;
private final int position;
public ReaderException(String name, int position, int codePoint, String message) {
super(message);
this.name = name;
this.codePoint = codePoint;
this.position = position;
}
public String getName() {
return name;
}
public int getCodePoint() {
return codePoint;
}
public int getPosition() {
return position;
}
@Override
public String toString() {
final String s = new String(Character.toChars(codePoint));
return "unacceptable code point '" + s + "' (0x"
+ Integer.toHexString(codePoint).toUpperCase() + ") " + getMessage()
+ "\nin \"" + name + "\", position " + position;
}
}

View File

@ -1,274 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.reader;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.scanner.Constant;
/**
* Reader: checks if code points are in allowed range, adds '\0' to the end.
*/
public class StreamReader {
private String name;
private final Reader stream;
private int pointer = 0; //in characters
private boolean eof = true;
private String buffer;
private int index = 0; //in characters
private int line = 0;
private int column = 0; //in code points
private char[] data;
private static final int BUFFER_SIZE = 1025;
public StreamReader(String stream) {
this.name = "'string'";
this.buffer = ""; // to set length to 0
checkPrintable(stream);
this.buffer = stream + "\0";
this.stream = null;
this.eof = true;
this.data = null;
}
public StreamReader(Reader reader) {
this.name = "'reader'";
this.buffer = "";
this.stream = reader;
this.eof = false;
this.data = new char[BUFFER_SIZE];
this.update();
}
void checkPrintable(String data) {
final int length = data.length();
for (int offset = 0; offset < length; ) {
final int codePoint = data.codePointAt(offset);
if (!isPrintable(codePoint)) {
throw new ReaderException(name, offset, codePoint,
"special characters are not allowed");
}
offset += Character.charCount(codePoint);
}
}
public static boolean isPrintable(final String data) {
final int length = data.length();
for (int offset = 0; offset < length; ) {
final int codePoint = data.codePointAt(offset);
if (!isPrintable(codePoint)) {
return false;
}
offset += Character.charCount(codePoint);
}
return true;
}
public static boolean isPrintable(final int c) {
return (c >= 0x20 && c <= 0x7E) || c == 0x9 || c == 0xA || c == 0xD
|| c == 0x85 || (c >= 0xA0 && c <= 0xD7FF)
|| (c >= 0xE000 && c <= 0xFFFD)
|| (c >= 0x10000 && c <= 0x10FFFF);
}
public Mark getMark() {
return new Mark(name, this.index, this.line, this.column, this.buffer, this.pointer);
}
public void forward() {
forward(1);
}
/**
* read the next length characters and move the pointer.
* if the last character is high surrogate one more character will be read
*
* @param length amount of characters to move forward
*/
public void forward(int length) {
int c;
for (int i = 0; i < length; i++) {
if (this.pointer == this.buffer.length()) {
update();
}
if (this.pointer == this.buffer.length()) {
break;
}
c = this.buffer.codePointAt(this.pointer);
this.pointer += Character.charCount(c);
this.index += Character.charCount(c);
if (Constant.LINEBR.has(c) || (c == '\r' && buffer.charAt(pointer) != '\n')) {
this.line++;
this.column = 0;
} else if (c != 0xFEFF) {
this.column++;
}
}
if (this.pointer == this.buffer.length()) {
update();
}
}
public int peek() {
if (this.pointer == this.buffer.length()) {
update();
}
if (this.pointer == this.buffer.length()) {
return -1;
}
return this.buffer.codePointAt(this.pointer);
}
/**
* Peek the next index-th code point
*
* @param index to peek
* @return the next index-th code point
*/
public int peek(int index) {
int offset = 0;
int nextIndex = 0;
int codePoint;
do {
if (this.pointer + offset == this.buffer.length()) {
update();
}
if (this.pointer + offset == this.buffer.length()) {
return -1;
}
codePoint = this.buffer.codePointAt(this.pointer + offset);
offset += Character.charCount(codePoint);
nextIndex++;
} while (nextIndex <= index);
return codePoint;
}
/**
* peek the next length code points
*
* @param length amount of the characters to peek
* @return the next length code points
*/
public String prefix(int length) {
final StringBuilder builder = new StringBuilder();
int offset = 0;
int resultLength = 0;
while (resultLength < length) {
if (this.pointer + offset == this.buffer.length()) {
update();
}
if (this.pointer + offset == this.buffer.length()) {
break;
}
int c = this.buffer.codePointAt(this.pointer + offset);
builder.appendCodePoint(c);
offset += Character.charCount(c);
resultLength++;
}
return builder.toString();
}
/**
* prefix(length) immediately followed by forward(length)
* @param length amount of characters to get
* @return the next length code points
*/
public String prefixForward(int length) {
final String prefix = prefix(length);
this.pointer += prefix.length();
this.index += prefix.length();
// prefix never contains new line characters
this.column += length;
return prefix;
}
private void update() {
if (!this.eof) {
this.buffer = buffer.substring(this.pointer);
this.pointer = 0;
try {
boolean eofDetected = false;
int converted = this.stream.read(data, 0, BUFFER_SIZE - 1);
if (converted > 0) {
if (Character.isHighSurrogate(data[converted - 1])) {
int oneMore = this.stream.read(data, converted, 1);
if (oneMore != -1) {
converted += oneMore;
} else {
eofDetected = true;
}
}
/*
* Let's create StringBuilder manually. Anyway str1 + str2
* generates new StringBuilder(str1).append(str2).toSting()
* Giving correct capacity to the constructor prevents
* unnecessary operations in appends.
*/
StringBuilder builder = new StringBuilder(buffer.length() + converted)
.append(buffer)
.append(data, 0, converted);
if (eofDetected) {
this.eof = true;
builder.append('\0');
}
this.buffer = builder.toString();
checkPrintable(this.buffer);
} else {
this.eof = true;
this.buffer += "\0";
}
} catch (IOException ioe) {
throw new YAMLException(ioe);
}
}
}
public int getColumn() {
return column;
}
public Charset getEncoding() {
return Charset.forName(((UnicodeReader) this.stream).getEncoding());
}
public int getIndex() {
return index;
}
public int getLine() {
return line;
}
}

View File

@ -1,127 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.reader;
/**
version: 1.1 / 2007-01-25
- changed BOM recognition ordering (longer boms first)
Original pseudocode : Thomas Weidenfeller
Implementation tweaked: Aki Nieminen
Implementation changed: Andrey Somov
* UTF-32 removed because it is not supported by YAML
* no default encoding
http://www.unicode.org/unicode/faq/utf_bom.html
BOMs:
00 00 FE FF = UTF-32, big-endian
FF FE 00 00 = UTF-32, little-endian
EF BB BF = UTF-8,
FE FF = UTF-16, big-endian
FF FE = UTF-16, little-endian
Win2k Notepad:
Unicode format = UTF-16LE
***/
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
/**
* Generic unicode textreader, which will use BOM mark to identify the encoding
* to be used. If BOM is not found then use a given default or system encoding.
*/
public class UnicodeReader extends Reader {
private static final Charset UTF8 = Charset.forName("UTF-8");
private static final Charset UTF16BE = Charset.forName("UTF-16BE");
private static final Charset UTF16LE = Charset.forName("UTF-16LE");
PushbackInputStream internalIn;
InputStreamReader internalIn2 = null;
private static final int BOM_SIZE = 3;
/**
* @param in
* InputStream to be read
*/
public UnicodeReader(InputStream in) {
internalIn = new PushbackInputStream(in, BOM_SIZE);
}
/**
* Get stream encoding or NULL if stream is uninitialized. Call init() or
* read() method to initialize it.
* @return the name of the character encoding being used by this stream.
*/
public String getEncoding() {
return internalIn2.getEncoding();
}
/**
* Read-ahead four bytes and check for BOM marks. Extra bytes are unread
* back to the stream, only BOM bytes are skipped.
* @throws IOException if InputStream cannot be created
*/
protected void init() throws IOException {
if (internalIn2 != null)
return;
Charset encoding;
byte bom[] = new byte[BOM_SIZE];
int n, unread;
n = internalIn.read(bom, 0, bom.length);
if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
encoding = UTF8;
unread = n - 3;
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
encoding = UTF16BE;
unread = n - 2;
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
encoding = UTF16LE;
unread = n - 2;
} else {
// Unicode BOM mark not found, unread all bytes
encoding = UTF8;
unread = n;
}
if (unread > 0)
internalIn.unread(bom, (n - unread), unread);
// Use given encoding
CharsetDecoder decoder = encoding.newDecoder().onUnmappableCharacter(
CodingErrorAction.REPORT);
internalIn2 = new InputStreamReader(internalIn, decoder);
}
public void close() throws IOException {
init();
internalIn2.close();
}
public int read(char[] cbuf, int off, int len) throws IOException {
init();
return internalIn2.read(cbuf, off, len);
}
}

View File

@ -1,202 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.representer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.DumperOptions.ScalarStyle;
import org.yaml.snakeyaml.introspector.PropertyUtils;
import org.yaml.snakeyaml.nodes.AnchorNode;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Represent basic YAML structures: scalar, sequence, mapping
*/
public abstract class BaseRepresenter {
protected final Map<Class<?>, Represent> representers = new HashMap<Class<?>, Represent>();
/**
* in Java 'null' is not a type. So we have to keep the null representer
* separately otherwise it will coincide with the default representer which
* is stored with the key null.
*/
protected Represent nullRepresenter;
// the order is important (map can be also a sequence of key-values)
protected final Map<Class<?>, Represent> multiRepresenters = new LinkedHashMap<Class<?>, Represent>();
protected Character defaultScalarStyle;
protected FlowStyle defaultFlowStyle = FlowStyle.AUTO;
protected final Map<Object, Node> representedObjects = new IdentityHashMap<Object, Node>() {
private static final long serialVersionUID = -5576159264232131854L;
public Node put(Object key, Node value) {
return super.put(key, new AnchorNode(value));
}
};
protected Object objectToRepresent;
private PropertyUtils propertyUtils;
private boolean explicitPropertyUtils = false;
public Node represent(Object data) {
Node node = representData(data);
representedObjects.clear();
objectToRepresent = null;
return node;
}
protected final Node representData(Object data) {
objectToRepresent = data;
// check for identity
if (representedObjects.containsKey(objectToRepresent)) {
Node node = representedObjects.get(objectToRepresent);
return node;
}
// }
// check for null first
if (data == null) {
Node node = nullRepresenter.representData(null);
return node;
}
// check the same class
Node node;
Class<?> clazz = data.getClass();
if (representers.containsKey(clazz)) {
Represent representer = representers.get(clazz);
node = representer.representData(data);
} else {
// check the parents
for (Class<?> repr : multiRepresenters.keySet()) {
if (repr != null && repr.isInstance(data)) {
Represent representer = multiRepresenters.get(repr);
node = representer.representData(data);
return node;
}
}
// check defaults
if (multiRepresenters.containsKey(null)) {
Represent representer = multiRepresenters.get(null);
node = representer.representData(data);
} else {
Represent representer = representers.get(null);
node = representer.representData(data);
}
}
return node;
}
protected Node representScalar(Tag tag, String value, Character style) {
if (style == null) {
style = this.defaultScalarStyle;
}
Node node = new ScalarNode(tag, value, null, null, style);
return node;
}
protected Node representScalar(Tag tag, String value) {
return representScalar(tag, value, null);
}
protected Node representSequence(Tag tag, Iterable<?> sequence, Boolean flowStyle) {
int size = 10;// default for ArrayList
if (sequence instanceof List<?>) {
size = ((List<?>) sequence).size();
}
List<Node> value = new ArrayList<Node>(size);
SequenceNode node = new SequenceNode(tag, value, flowStyle);
representedObjects.put(objectToRepresent, node);
boolean bestStyle = true;
for (Object item : sequence) {
Node nodeItem = representData(item);
if (!(nodeItem instanceof ScalarNode && ((ScalarNode) nodeItem).getStyle() == null)) {
bestStyle = false;
}
value.add(nodeItem);
}
if (flowStyle == null) {
if (defaultFlowStyle != FlowStyle.AUTO) {
node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
} else {
node.setFlowStyle(bestStyle);
}
}
return node;
}
protected Node representMapping(Tag tag, Map<?, ?> mapping, Boolean flowStyle) {
List<NodeTuple> value = new ArrayList<NodeTuple>(mapping.size());
MappingNode node = new MappingNode(tag, value, flowStyle);
representedObjects.put(objectToRepresent, node);
boolean bestStyle = true;
for (Map.Entry<?, ?> entry : mapping.entrySet()) {
Node nodeKey = representData(entry.getKey());
Node nodeValue = representData(entry.getValue());
if (!(nodeKey instanceof ScalarNode && ((ScalarNode) nodeKey).getStyle() == null)) {
bestStyle = false;
}
if (!(nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null)) {
bestStyle = false;
}
value.add(new NodeTuple(nodeKey, nodeValue));
}
if (flowStyle == null) {
if (defaultFlowStyle != FlowStyle.AUTO) {
node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
} else {
node.setFlowStyle(bestStyle);
}
}
return node;
}
public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
this.defaultScalarStyle = defaultStyle.getChar();
}
public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
this.defaultFlowStyle = defaultFlowStyle;
}
public FlowStyle getDefaultFlowStyle() {
return this.defaultFlowStyle;
}
public void setPropertyUtils(PropertyUtils propertyUtils) {
this.propertyUtils = propertyUtils;
this.explicitPropertyUtils = true;
}
public final PropertyUtils getPropertyUtils() {
if (propertyUtils == null) {
propertyUtils = new PropertyUtils();
}
return propertyUtils;
}
public final boolean isExplicitPropertyUtils() {
return explicitPropertyUtils;
}
}

View File

@ -1,36 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.representer;
import org.yaml.snakeyaml.nodes.Node;
/**
* Create a Node Graph out of the provided Native Data Structure (Java
* instance).
*
* @see <a href="http://yaml.org/spec/1.1/#id859109">Chapter 3. Processing YAML
* Information</a>
*/
public interface Represent {
/**
* Create a Node
*
* @param data
* the instance to represent
* @return Node to dump
*/
Node representData(Object data);
}

View File

@ -1,249 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.representer;
import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Represent JavaBeans
*/
public class Representer extends SafeRepresenter {
public Representer() {
this.representers.put(null, new RepresentJavaBean());
}
protected class RepresentJavaBean implements Represent {
public Node representData(Object data) {
try {
return representJavaBean(getProperties(data.getClass()), data);
} catch (IntrospectionException e) {
throw new YAMLException(e);
}
}
}
/**
* Tag logic:
* - explicit root tag is set in serializer
* - if there is a predefined class tag it is used
* - a global tag with class name is always used as tag. The JavaBean parent
* of the specified JavaBean may set another tag (tag:yaml.org,2002:map)
* when the property class is the same as runtime class
*
* @param properties
* JavaBean getters
* @param javaBean
* instance for Node
* @return Node to get serialized
*/
protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
List<NodeTuple> value = new ArrayList<NodeTuple>(properties.size());
Tag tag;
Tag customTag = classTags.get(javaBean.getClass());
tag = customTag != null ? customTag : new Tag(javaBean.getClass());
// flow style will be chosen by BaseRepresenter
MappingNode node = new MappingNode(tag, value, null);
representedObjects.put(javaBean, node);
boolean bestStyle = true;
for (Property property : properties) {
Object memberValue = property.get(javaBean);
Tag customPropertyTag = memberValue == null ? null : classTags.get(memberValue
.getClass());
NodeTuple tuple = representJavaBeanProperty(javaBean, property, memberValue,
customPropertyTag);
if (tuple == null) {
continue;
}
if (((ScalarNode) tuple.getKeyNode()).getStyle() != null) {
bestStyle = false;
}
Node nodeValue = tuple.getValueNode();
if (!(nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null)) {
bestStyle = false;
}
value.add(tuple);
}
if (defaultFlowStyle != FlowStyle.AUTO) {
node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
} else {
node.setFlowStyle(bestStyle);
}
return node;
}
/**
* Represent one JavaBean property.
*
* @param javaBean
* - the instance to be represented
* @param property
* - the property of the instance
* @param propertyValue
* - value to be represented
* @param customTag
* - user defined Tag
* @return NodeTuple to be used in a MappingNode. Return null to skip the
* property
*/
protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
Object propertyValue, Tag customTag) {
ScalarNode nodeKey = (ScalarNode) representData(property.getName());
// the first occurrence of the node must keep the tag
boolean hasAlias = this.representedObjects.containsKey(propertyValue);
Node nodeValue = representData(propertyValue);
if (propertyValue != null && !hasAlias) {
NodeId nodeId = nodeValue.getNodeId();
if (customTag == null) {
if (nodeId == NodeId.scalar) {
if (propertyValue instanceof Enum<?>) {
nodeValue.setTag(Tag.STR);
}
} else {
if (nodeId == NodeId.mapping) {
if (property.getType() == propertyValue.getClass()) {
if (!(propertyValue instanceof Map<?, ?>)) {
if (!nodeValue.getTag().equals(Tag.SET)) {
nodeValue.setTag(Tag.MAP);
}
}
}
}
checkGlobalTag(property, nodeValue, propertyValue);
}
}
}
return new NodeTuple(nodeKey, nodeValue);
}
/**
* Remove redundant global tag for a type safe (generic) collection if it is
* the same as defined by the JavaBean property
*
* @param property
* - JavaBean property
* @param node
* - representation of the property
* @param object
* - instance represented by the node
*/
@SuppressWarnings("unchecked")
protected void checkGlobalTag(Property property, Node node, Object object) {
// Skip primitive arrays.
if (object.getClass().isArray() && object.getClass().getComponentType().isPrimitive()) {
return;
}
Class<?>[] arguments = property.getActualTypeArguments();
if (arguments != null) {
if (node.getNodeId() == NodeId.sequence) {
// apply map tag where class is the same
Class<? extends Object> t = arguments[0];
SequenceNode snode = (SequenceNode) node;
Iterable<Object> memberList = Collections.EMPTY_LIST;
if (object.getClass().isArray()) {
memberList = Arrays.asList((Object[]) object);
} else if (object instanceof Iterable<?>) {
// list
memberList = (Iterable<Object>) object;
}
Iterator<Object> iter = memberList.iterator();
if (iter.hasNext()) {
for (Node childNode : snode.getValue()) {
Object member = iter.next();
if (member != null) {
if (t.equals(member.getClass()))
if (childNode.getNodeId() == NodeId.mapping) {
childNode.setTag(Tag.MAP);
}
}
}
}
} else if (object instanceof Set) {
Class<?> t = arguments[0];
MappingNode mnode = (MappingNode) node;
Iterator<NodeTuple> iter = mnode.getValue().iterator();
Set<?> set = (Set<?>) object;
for (Object member : set) {
NodeTuple tuple = iter.next();
Node keyNode = tuple.getKeyNode();
if (t.equals(member.getClass())) {
if (keyNode.getNodeId() == NodeId.mapping) {
keyNode.setTag(Tag.MAP);
}
}
}
} else if (object instanceof Map) {
Class<?> keyType = arguments[0];
Class<?> valueType = arguments[1];
MappingNode mnode = (MappingNode) node;
for (NodeTuple tuple : mnode.getValue()) {
resetTag(keyType, tuple.getKeyNode());
resetTag(valueType, tuple.getValueNode());
}
} else {
// the type for collection entries cannot be
// detected
}
}
}
private void resetTag(Class<? extends Object> type, Node node) {
Tag tag = node.getTag();
if (tag.matches(type)) {
if (Enum.class.isAssignableFrom(type)) {
node.setTag(Tag.STR);
} else {
node.setTag(Tag.MAP);
}
}
}
/**
* Get JavaBean properties to be serialised. The order is respected. This
* method may be overridden to provide custom property selection or order.
*
* @param type
* - JavaBean to inspect the properties
* @return properties to serialise
* @throws IntrospectionException if the class cannot be introspacted
*/
protected Set<Property> getProperties(Class<? extends Object> type)
throws IntrospectionException {
return getPropertyUtils().getProperties(type);
}
}

View File

@ -1,434 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.representer;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.reader.StreamReader;
/**
* Represent standard Java classes
*/
class SafeRepresenter extends BaseRepresenter {
protected Map<Class<? extends Object>, Tag> classTags;
protected TimeZone timeZone = null;
public SafeRepresenter() {
this.nullRepresenter = new RepresentNull();
this.representers.put(String.class, new RepresentString());
this.representers.put(Boolean.class, new RepresentBoolean());
this.representers.put(Character.class, new RepresentString());
this.representers.put(UUID.class, new RepresentUuid());
this.representers.put(byte[].class, new RepresentByteArray());
Represent primitiveArray = new RepresentPrimitiveArray();
representers.put(short[].class, primitiveArray);
representers.put(int[].class, primitiveArray);
representers.put(long[].class, primitiveArray);
representers.put(float[].class, primitiveArray);
representers.put(double[].class, primitiveArray);
representers.put(char[].class, primitiveArray);
representers.put(boolean[].class, primitiveArray);
this.multiRepresenters.put(Number.class, new RepresentNumber());
this.multiRepresenters.put(List.class, new RepresentList());
this.multiRepresenters.put(Map.class, new RepresentMap());
this.multiRepresenters.put(Set.class, new RepresentSet());
this.multiRepresenters.put(Iterator.class, new RepresentIterator());
this.multiRepresenters.put(new Object[0].getClass(), new RepresentArray());
this.multiRepresenters.put(Date.class, new RepresentDate());
this.multiRepresenters.put(Enum.class, new RepresentEnum());
this.multiRepresenters.put(Calendar.class, new RepresentDate());
classTags = new HashMap<Class<? extends Object>, Tag>();
}
protected Tag getTag(Class<?> clazz, Tag defaultTag) {
if (classTags.containsKey(clazz)) {
return classTags.get(clazz);
} else {
return defaultTag;
}
}
/**
* Define a tag for the <code>Class</code> to serialize.
*
* @param clazz
* <code>Class</code> which tag is changed
* @param tag
* new tag to be used for every instance of the specified
* <code>Class</code>
* @return the previous tag associated with the <code>Class</code>
*/
public Tag addClassTag(Class<? extends Object> clazz, Tag tag) {
if (tag == null) {
throw new NullPointerException("Tag must be provided.");
}
return classTags.put(clazz, tag);
}
protected class RepresentNull implements Represent {
public Node representData(Object data) {
return representScalar(Tag.NULL, "null");
}
}
public static Pattern MULTILINE_PATTERN = Pattern.compile("\n|\u0085|\u2028|\u2029");
protected class RepresentString implements Represent {
public Node representData(Object data) {
Tag tag = Tag.STR;
Character style = null;
String value = data.toString();
if (!StreamReader.isPrintable(value)) {
tag = Tag.BINARY;
char[] binary;
try {
final byte[] bytes = value.getBytes("UTF-8");
// sometimes above will just silently fail - it will return incomplete data
// it happens when String has invalid code points
// (for example half surrogate character without other half)
final String checkValue = new String(bytes, "UTF-8");
if (!checkValue.equals(value)) {
throw new YAMLException("invalid string value has occurred");
}
binary = Base64Coder.encode(bytes);
} catch (UnsupportedEncodingException e) {
throw new YAMLException(e);
}
value = String.valueOf(binary);
style = '|';
}
// if no other scalar style is explicitly set, use literal style for
// multiline scalars
if (defaultScalarStyle == null && MULTILINE_PATTERN.matcher(value).find()) {
style = '|';
}
return representScalar(tag, value, style);
}
}
protected class RepresentBoolean implements Represent {
public Node representData(Object data) {
String value;
if (Boolean.TRUE.equals(data)) {
value = "true";
} else {
value = "false";
}
return representScalar(Tag.BOOL, value);
}
}
protected class RepresentNumber implements Represent {
public Node representData(Object data) {
Tag tag;
String value;
if (data instanceof Byte || data instanceof Short || data instanceof Integer
|| data instanceof Long || data instanceof BigInteger) {
tag = Tag.INT;
value = data.toString();
} else {
Number number = (Number) data;
tag = Tag.FLOAT;
if (number.equals(Double.NaN)) {
value = ".NaN";
} else if (number.equals(Double.POSITIVE_INFINITY)) {
value = ".inf";
} else if (number.equals(Double.NEGATIVE_INFINITY)) {
value = "-.inf";
} else {
value = number.toString();
}
}
return representScalar(getTag(data.getClass(), tag), value);
}
}
protected class RepresentList implements Represent {
@SuppressWarnings("unchecked")
public Node representData(Object data) {
return representSequence(getTag(data.getClass(), Tag.SEQ), (List<Object>) data, null);
}
}
protected class RepresentIterator implements Represent {
@SuppressWarnings("unchecked")
public Node representData(Object data) {
Iterator<Object> iter = (Iterator<Object>) data;
return representSequence(getTag(data.getClass(), Tag.SEQ), new IteratorWrapper(iter),
null);
}
}
private static class IteratorWrapper implements Iterable<Object> {
private Iterator<Object> iter;
public IteratorWrapper(Iterator<Object> iter) {
this.iter = iter;
}
public Iterator<Object> iterator() {
return iter;
}
}
protected class RepresentArray implements Represent {
public Node representData(Object data) {
Object[] array = (Object[]) data;
List<Object> list = Arrays.asList(array);
return representSequence(Tag.SEQ, list, null);
}
}
/**
* Represents primitive arrays, such as short[] and float[], by converting
* them into equivalent List<Short> and List<Float> using the appropriate
* autoboxing type.
*/
protected class RepresentPrimitiveArray implements Represent {
public Node representData(Object data) {
Class<?> type = data.getClass().getComponentType();
if (byte.class == type) {
return representSequence(Tag.SEQ, asByteList(data), null);
} else if (short.class == type) {
return representSequence(Tag.SEQ, asShortList(data), null);
} else if (int.class == type) {
return representSequence(Tag.SEQ, asIntList(data), null);
} else if (long.class == type) {
return representSequence(Tag.SEQ, asLongList(data), null);
} else if (float.class == type) {
return representSequence(Tag.SEQ, asFloatList(data), null);
} else if (double.class == type) {
return representSequence(Tag.SEQ, asDoubleList(data), null);
} else if (char.class == type) {
return representSequence(Tag.SEQ, asCharList(data), null);
} else if (boolean.class == type) {
return representSequence(Tag.SEQ, asBooleanList(data), null);
}
throw new YAMLException("Unexpected primitive '" + type.getCanonicalName() + "'");
}
private List<Byte> asByteList(Object in) {
byte[] array = (byte[]) in;
List<Byte> list = new ArrayList<Byte>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Short> asShortList(Object in) {
short[] array = (short[]) in;
List<Short> list = new ArrayList<Short>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Integer> asIntList(Object in) {
int[] array = (int[]) in;
List<Integer> list = new ArrayList<Integer>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Long> asLongList(Object in) {
long[] array = (long[]) in;
List<Long> list = new ArrayList<Long>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Float> asFloatList(Object in) {
float[] array = (float[]) in;
List<Float> list = new ArrayList<Float>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Double> asDoubleList(Object in) {
double[] array = (double[]) in;
List<Double> list = new ArrayList<Double>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Character> asCharList(Object in) {
char[] array = (char[]) in;
List<Character> list = new ArrayList<Character>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
private List<Boolean> asBooleanList(Object in) {
boolean[] array = (boolean[]) in;
List<Boolean> list = new ArrayList<Boolean>(array.length);
for (int i = 0; i < array.length; ++i)
list.add(array[i]);
return list;
}
}
protected class RepresentMap implements Represent {
@SuppressWarnings("unchecked")
public Node representData(Object data) {
return representMapping(getTag(data.getClass(), Tag.MAP), (Map<Object, Object>) data,
null);
}
}
protected class RepresentSet implements Represent {
@SuppressWarnings("unchecked")
public Node representData(Object data) {
Map<Object, Object> value = new LinkedHashMap<Object, Object>();
Set<Object> set = (Set<Object>) data;
for (Object key : set) {
value.put(key, null);
}
return representMapping(getTag(data.getClass(), Tag.SET), value, null);
}
}
protected class RepresentDate implements Represent {
public Node representData(Object data) {
// because SimpleDateFormat ignores timezone we have to use Calendar
Calendar calendar;
if (data instanceof Calendar) {
calendar = (Calendar) data;
} else {
calendar = Calendar.getInstance(getTimeZone() == null ? TimeZone.getTimeZone("UTC")
: timeZone);
calendar.setTime((Date) data);
}
int years = calendar.get(Calendar.YEAR);
int months = calendar.get(Calendar.MONTH) + 1; // 0..12
int days = calendar.get(Calendar.DAY_OF_MONTH); // 1..31
int hour24 = calendar.get(Calendar.HOUR_OF_DAY); // 0..24
int minutes = calendar.get(Calendar.MINUTE); // 0..59
int seconds = calendar.get(Calendar.SECOND); // 0..59
int millis = calendar.get(Calendar.MILLISECOND);
StringBuilder buffer = new StringBuilder(String.valueOf(years));
while (buffer.length() < 4) {
// ancient years
buffer.insert(0, "0");
}
buffer.append("-");
if (months < 10) {
buffer.append("0");
}
buffer.append(String.valueOf(months));
buffer.append("-");
if (days < 10) {
buffer.append("0");
}
buffer.append(String.valueOf(days));
buffer.append("T");
if (hour24 < 10) {
buffer.append("0");
}
buffer.append(String.valueOf(hour24));
buffer.append(":");
if (minutes < 10) {
buffer.append("0");
}
buffer.append(String.valueOf(minutes));
buffer.append(":");
if (seconds < 10) {
buffer.append("0");
}
buffer.append(String.valueOf(seconds));
if (millis > 0) {
if (millis < 10) {
buffer.append(".00");
} else if (millis < 100) {
buffer.append(".0");
} else {
buffer.append(".");
}
buffer.append(String.valueOf(millis));
}
if (TimeZone.getTimeZone("UTC").equals(calendar.getTimeZone())) {
buffer.append("Z");
} else {
// Get the Offset from GMT taking DST into account
int gmtOffset = calendar.getTimeZone().getOffset(calendar.get(Calendar.ERA),
calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK),
calendar.get(Calendar.MILLISECOND));
int minutesOffset = gmtOffset / (60 * 1000);
int hoursOffset = minutesOffset / 60;
int partOfHour = minutesOffset % 60;
buffer.append((hoursOffset > 0 ? "+" : "") + hoursOffset + ":"
+ (partOfHour < 10 ? "0" + partOfHour : partOfHour));
}
return representScalar(getTag(data.getClass(), Tag.TIMESTAMP), buffer.toString(), null);
}
}
protected class RepresentEnum implements Represent {
public Node representData(Object data) {
Tag tag = new Tag(data.getClass());
return representScalar(getTag(data.getClass(), tag), ((Enum<?>) data).name());
}
}
protected class RepresentByteArray implements Represent {
public Node representData(Object data) {
char[] binary = Base64Coder.encode((byte[]) data);
return representScalar(Tag.BINARY, String.valueOf(binary), '|');
}
}
public TimeZone getTimeZone() {
return timeZone;
}
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
protected class RepresentUuid implements Represent {
public Node representData(Object data) {
return representScalar(getTag(data.getClass(), new Tag(UUID.class)), data.toString());
}
}
}

View File

@ -1,138 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.resolver;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Resolver tries to detect a type by content (when the tag is implicit)
*/
public class Resolver {
public static final Pattern BOOL = Pattern
.compile("^(?:yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$");
/**
* The regular expression is taken from the 1.2 specification but '_'s are
* added to keep backwards compatibility
*/
public static final Pattern FLOAT = Pattern
.compile("^([-+]?(\\.[0-9]+|[0-9_]+(\\.[0-9_]*)?)([eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");
public static final Pattern INT = Pattern
.compile("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$");
public static final Pattern MERGE = Pattern.compile("^(?:<<)$");
public static final Pattern NULL = Pattern.compile("^(?:~|null|Null|NULL| )$");
public static final Pattern EMPTY = Pattern.compile("^$");
public static final Pattern TIMESTAMP = Pattern
.compile("^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$");
public static final Pattern VALUE = Pattern.compile("^(?:=)$");
public static final Pattern YAML = Pattern.compile("^(?:!|&|\\*)$");
protected Map<Character, List<ResolverTuple>> yamlImplicitResolvers = new HashMap<Character, List<ResolverTuple>>();
protected void addImplicitResolvers() {
addImplicitResolver(Tag.BOOL, BOOL, "yYnNtTfFoO");
/*
* INT must be before FLOAT because the regular expression for FLOAT
* matches INT (see issue 130)
* http://code.google.com/p/snakeyaml/issues/detail?id=130
*/
addImplicitResolver(Tag.INT, INT, "-+0123456789");
addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
addImplicitResolver(Tag.MERGE, MERGE, "<");
addImplicitResolver(Tag.NULL, NULL, "~nN\0");
addImplicitResolver(Tag.NULL, EMPTY, null);
addImplicitResolver(Tag.TIMESTAMP, TIMESTAMP, "0123456789");
// The following implicit resolver is only for documentation
// purposes.
// It cannot work
// because plain scalars cannot start with '!', '&', or '*'.
addImplicitResolver(Tag.YAML, YAML, "!&*");
}
public Resolver() {
addImplicitResolvers();
}
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
if (first == null) {
List<ResolverTuple> curr = yamlImplicitResolvers.get(null);
if (curr == null) {
curr = new ArrayList<ResolverTuple>();
yamlImplicitResolvers.put(null, curr);
}
curr.add(new ResolverTuple(tag, regexp));
} else {
char[] chrs = first.toCharArray();
for (int i = 0, j = chrs.length; i < j; i++) {
Character theC = Character.valueOf(chrs[i]);
if (theC == 0) {
// special case: for null
theC = null;
}
List<ResolverTuple> curr = yamlImplicitResolvers.get(theC);
if (curr == null) {
curr = new ArrayList<ResolverTuple>();
yamlImplicitResolvers.put(theC, curr);
}
curr.add(new ResolverTuple(tag, regexp));
}
}
}
public Tag resolve(NodeId kind, String value, boolean implicit) {
if (kind == NodeId.scalar && implicit) {
List<ResolverTuple> resolvers = null;
if (value.length() == 0) {
resolvers = yamlImplicitResolvers.get('\0');
} else {
resolvers = yamlImplicitResolvers.get(value.charAt(0));
}
if (resolvers != null) {
for (ResolverTuple v : resolvers) {
Tag tag = v.getTag();
Pattern regexp = v.getRegexp();
if (regexp.matcher(value).matches()) {
return tag;
}
}
}
if (yamlImplicitResolvers.containsKey(null)) {
for (ResolverTuple v : yamlImplicitResolvers.get(null)) {
Tag tag = v.getTag();
Pattern regexp = v.getRegexp();
if (regexp.matcher(value).matches()) {
return tag;
}
}
}
}
switch (kind) {
case scalar:
return Tag.STR;
case sequence:
return Tag.SEQ;
default:
return Tag.MAP;
}
}
}

View File

@ -1,43 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.resolver;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.nodes.Tag;
final class ResolverTuple {
private final Tag tag;
private final Pattern regexp;
public ResolverTuple(Tag tag, Pattern regexp) {
this.tag = tag;
this.regexp = regexp;
}
public Tag getTag() {
return tag;
}
public Pattern getRegexp() {
return regexp;
}
@Override
public String toString() {
return "Tuple tag=" + tag + " regexp=" + regexp;
}
}

View File

@ -1,76 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.scanner;
import java.util.Arrays;
public final class Constant {
private final static String ALPHA_S = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
private final static String LINEBR_S = "\n\u0085\u2028\u2029";
private final static String FULL_LINEBR_S = "\r" + LINEBR_S;
private final static String NULL_OR_LINEBR_S = "\0" + FULL_LINEBR_S;
private final static String NULL_BL_LINEBR_S = " " + NULL_OR_LINEBR_S;
private final static String NULL_BL_T_LINEBR_S = "\t" + NULL_BL_LINEBR_S;
private final static String NULL_BL_T_S = "\0 \t";
private final static String URI_CHARS_S = ALPHA_S + "-;/?:@&=+$,_.!~*\'()[]%";
public final static Constant LINEBR = new Constant(LINEBR_S);
public final static Constant FULL_LINEBR = new Constant(FULL_LINEBR_S);
public final static Constant NULL_OR_LINEBR = new Constant(NULL_OR_LINEBR_S);
public final static Constant NULL_BL_LINEBR = new Constant(NULL_BL_LINEBR_S);
public final static Constant NULL_BL_T_LINEBR = new Constant(NULL_BL_T_LINEBR_S);
public final static Constant NULL_BL_T = new Constant(NULL_BL_T_S);
public final static Constant URI_CHARS = new Constant(URI_CHARS_S);
public final static Constant ALPHA = new Constant(ALPHA_S);
private String content;
boolean[] contains = new boolean[128];
boolean noASCII = false;
private Constant(String content) {
Arrays.fill(contains, false);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < content.length(); i++) {
int c = content.codePointAt(i);
if (c < 128)
contains[c] = true;
else
sb.appendCodePoint(c);
}
if (sb.length() > 0) {
noASCII = true;
this.content = sb.toString();
}
}
public boolean has(int c) {
return (c < 128) ? contains[c] : noASCII && content.indexOf(c, 0) != -1;
}
public boolean hasNo(int c) {
return !has(c);
}
public boolean has(int c, String additional) {
return has(c) || additional.indexOf(c, 0) != -1;
}
public boolean hasNo(int c, String additional) {
return !has(c, additional);
}
}

View File

@ -1,65 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.scanner;
import org.yaml.snakeyaml.tokens.Token;
/**
* This interface represents an input stream of {@link Token Tokens}.
* <p>
* The parser and the scanner form together the 'Parse' step in the loading
* process (see chapter 3.1 of the <a href="http://yaml.org/spec/1.1/">YAML
* Specification</a>).
* </p>
*
* @see org.yaml.snakeyaml.tokens.Token
*/
public interface Scanner {
/**
* Check if the next token is one of the given types.
*
* @param choices
* token IDs.
* @return <code>true</code> if the next token can be assigned to a variable
* of at least one of the given types. Returns <code>false</code> if
* no more tokens are available.
* @throws ScannerException
* Thrown in case of malformed input.
*/
boolean checkToken(Token.ID... choices);
/**
* Return the next token, but do not delete it from the stream.
*
* @return The token that will be returned on the next call to
* {@link #getToken}
* @throws ScannerException
* Thrown in case of malformed input.
*/
Token peekToken();
/**
* Returns the next token.
* <p>
* The token will be removed from the stream.
* </p>
* @return the coming token
* @throws ScannerException
* Thrown in case of malformed input.
*/
Token getToken();
}

View File

@ -1,66 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.scanner;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.error.MarkedYAMLException;
/**
* Exception thrown by the {@link Scanner} implementations in case of malformed
* input.
*/
public class ScannerException extends MarkedYAMLException {
private static final long serialVersionUID = 4782293188600445954L;
/**
* Constructs an instance.
*
* @param context
* Part of the input document in which vicinity the problem
* occurred.
* @param contextMark
* Position of the <code>context</code> within the document.
* @param problem
* Part of the input document that caused the problem.
* @param problemMark
* Position of the <code>problem</code> within the document.
* @param note
* Message for the user with further information about the
* problem.
*/
public ScannerException(String context, Mark contextMark, String problem, Mark problemMark,
String note) {
super(context, contextMark, problem, problemMark, note);
}
/**
* Constructs an instance.
*
* @param context
* Part of the input document in which vicinity the problem
* occurred.
* @param contextMark
* Position of the <code>context</code> within the document.
* @param problem
* Part of the input document that caused the problem.
* @param problemMark
* Position of the <code>problem</code> within the document.
*/
public ScannerException(String context, Mark contextMark, String problem, Mark problemMark) {
this(context, contextMark, problem, problemMark, null);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.scanner;
import org.yaml.snakeyaml.error.Mark;
/**
* Simple keys treatment.
* <p>
* Helper class for {@link ScannerImpl}.
* </p>
*
* @see ScannerImpl
*/
final class SimpleKey {
private int tokenNumber;
private boolean required;
private int index;
private int line;
private int column;
private Mark mark;
public SimpleKey(int tokenNumber, boolean required, int index, int line, int column, Mark mark) {
this.tokenNumber = tokenNumber;
this.required = required;
this.index = index;
this.line = line;
this.column = column;
this.mark = mark;
}
public int getTokenNumber() {
return this.tokenNumber;
}
public int getColumn() {
return this.column;
}
public Mark getMark() {
return mark;
}
public int getIndex() {
return index;
}
public int getLine() {
return line;
}
public boolean isRequired() {
return required;
}
@Override
public String toString() {
return "SimpleKey - tokenNumber=" + tokenNumber + " required=" + required + " index="
+ index + " line=" + line + " column=" + column;
}
}

View File

@ -1,23 +0,0 @@
/**
* Copyright (c) 2008, http://www.snakeyaml.org
*
* 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.yaml.snakeyaml.serializer;
import org.yaml.snakeyaml.nodes.Node;
public interface AnchorGenerator {
String nextAnchor(Node node);
}

Some files were not shown because too many files have changed in this diff Show More